powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / констрейнт на таблицу
25 сообщений из 26, страница 1 из 2
констрейнт на таблицу
    #36094072
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
допустим есть такие таблицы (естественно, здесь только нужные для понимания моей проблемы столбцы; определения писал вручную, возможны ошибки, но думаю, суть понятна)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create table Contracts (
	Contract_nbr nvarchar( 20 ) not null primary key,
	Company_id int not null
)

create table Payments (
	Payment_nbr nvarchar( 20 ) not null primary key,
             Payment_amount money not null,
	Contract_nbr nvarchar( 20 ) not null,
	constraint Payments_contracts_fk foreign key (Contract_nbr) 
		references Contracts (Contract_nbr)
)

create table Docs(
	Doc_nbr nvarchar( 20 ) not null primary key,
             Doc_amount money not null,
	Contract_nbr nvarchar( 20 ) not null,
	constraint Docs_contracts_fk foreign key (Contract_nbr) 
		references Contracts (Contract_nbr)
)
Для связи многие-ко-многим между Payments и Docs нужна ассоциативная таблица Payments_docs cо столбцами Payment_nbr nvarchar(20), Doc_nbr nvarchar(20), Allocated_amount money для соотнесения платежей и расчетных документов. Вроде бы просто, но есть проблема, которую не могу решить. Хочу констрейнт (внешний ключ? уникальный индекс? CHECK?) на эту таблицу, который бы не давал вводить запись с документом и платежом, относящимся к разным договорам.

Для общего понимания: я - любитель, базу делаю на Аксессе для приятеля, записей будет мало, но хочу сделать по возможности грамотно.

Прошу помочь, у кого есть идея, как это реализовать.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094254
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. храни ид договора дополнительно в таблице
2. внешние ключи делай по двум полям
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094318
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator Arepoкак это реализовать.Где-то так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
CREATE TABLE Company (
	ID int PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
)

CREATE TABLE Contract (
	ID int PRIMARY KEY
	, Contract_nbr nvarchar( 20 ) NOT NULL UNIQUE
	, Company_id int NOT NULL REFERENCES Company (ID)
)

CREATE TABLE Payment (
	Contract_ID int NOT NULL REFERENCES Contract (ID)
	, ID int NOT NULL
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, PRIMARY KEY (Contract_ID, ID)
)

CREATE TABLE Doc (
	Contract_ID int NOT NULL REFERENCES Contract (ID)
	, ID int NOT NULL
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, PRIMARY KEY (Contract_ID, ID)
)

CREATE TABLE Payment_Doc (
	Contract_ID int NOT NULL
	, Payment_ID int NOT NULL
	, Doc_ID int NOT NULL
	, CONSTRAINT Payment_fk FOREIGN KEY (Contract_ID, Payment_ID) REFERENCES Payment (Contract_ID, ID)
	, CONSTRAINT Doc_fk FOREIGN KEY (Contract_ID, Doc_ID) REFERENCES Doc (Contract_ID, ID)
)
Миграция больших полей допустима, но не приветствуется, так как сравнение 2 int-ов происходит обычно быстрее, чем 2-х nvarchar(20). В Вашей ситуации это вряд ли критично, но лучше сразу подстраховаться. Кроме того, естественные ключи имеют тенденцию меняться, что тоже неприятно, хотя опять же несмертельно в Вашей задаче. Но тем не менее, разумнее сразу использовать суррогатные ключи при реализации ссылочной целостности.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094429
Фотография Restavraciya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторбазу делаю на Аксессе ...
Хочу констрейнт (внешний ключ? уникальный индекс? CHECK?) на эту таблицу, который бы не давал вводить запись с документом и платежом, относящимся к разным договорам.
Вроде так работает
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create table Payments_docs (
  id counter not null primary key,
  Payment_nbr nvarchar( 20 ) not null,
  Doc_nbr nvarchar( 20 ) not null
)

alter table Payments_docs add constraint WARNING1 check (
   (select count(P.Contract_nbr) from Payments P inner join Docs D on P.Contract_nbr=D.Contract_nbr 
    where P.Payment_nbr=Payments_docs.Payment_nbr and D.Doc_nbr=Payments_docs.Doc_nbr)> 0 
)
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094525
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChA............


Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE TABLE Payment_Doc (
	Contract_ID int NOT NULL
	, Payment_ID int NOT NULL
	, Doc_ID int NOT NULL
	, CONSTRAINT Payment_fk FOREIGN KEY (Contract_ID, Payment_ID) REFERENCES Payment (Contract_ID, ID)
	, CONSTRAINT Doc_fk FOREIGN KEY (Contract_ID, Doc_ID) REFERENCES Doc (Contract_ID, ID)
)
Миграция больших полей допустима, но не приветствуется, так как сравнение 2 int-ов происходит обычно быстрее, чем 2-х nvarchar(20). В Вашей ситуации это вряд ли критично, но лучше сразу подстраховаться. Кроме того, естественные ключи имеют тенденцию меняться, что тоже неприятно, хотя опять же несмертельно в Вашей задаче. Но тем не менее, разумнее сразу использовать суррогатные ключи при реализации ссылочной целостности.
Спасибо за ответ - и за тонкий намек поменять мой стиль наименования на Ваш :-) .
Что есть первичный ключ в таблице Payment_Doc?
По поводу ключей в моих таблицах: в реальности они и есть автосчетчики. Пытался упростить объяснение и опустить ненужные с моей точки зрения детали.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094526
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Restavraciyaавторбазу делаю на Аксессе ...
Хочу констрейнт (внешний ключ? уникальный индекс? CHECK?) на эту таблицу, который бы не давал вводить запись с документом и платежом, относящимся к разным договорам.
Вроде так работает
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create table Payments_docs (
  id counter not null primary key,
  Payment_nbr nvarchar( 20 ) not null,
  Doc_nbr nvarchar( 20 ) not null
)

alter table Payments_docs add constraint WARNING1 check (
   (select count(P.Contract_nbr) from Payments P inner join Docs D on P.Contract_nbr=D.Contract_nbr 
    where P.Payment_nbr=Payments_docs.Payment_nbr and D.Doc_nbr=Payments_docs.Doc_nbr)> 0 
)

Реставрация, спасибо, попробую - чувствую, что это то, что мне надо.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094588
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator Arepoза тонкий намек поменять мой стиль наименования на ВашДаже и не думал, это просто привычка.

Sator ArepoЧто есть первичный ключ в таблице Payment_Doc?Sorry, забыл. Так как подразумевалась уникальность ID только в комбинации с Contract_ID, то, пожалуй, так - PRIMARY KEY(Contract_ID, Payment_ID, Doc_ID).
В то же время, если ID в соответствующих таблицах уникальны сами по себе, то вполне будет достаточно комбинации (Payment_ID, Doc_ID). Тогда, пожалуй, схему лучше изобразить так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
CREATE TABLE Company (
	ID int PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
)

CREATE TABLE Contract (
	ID int PRIMARY KEY
	, Contract_nbr nvarchar( 20 ) NOT NULL UNIQUE
	, Company_id int NOT NULL REFERENCES Company (ID)
)

CREATE TABLE Payment (
	Contract_ID int NOT NULL REFERENCES Contract (ID)
	, ID int NOT NULL PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, UNIQUE (Contract_ID, ID)
)

CREATE TABLE Doc (
	Contract_ID int NOT NULL REFERENCES Contract (ID)
	, ID int NOT NULL PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, UNIQUE (Contract_ID, ID)
)

CREATE TABLE Payment_Doc (
	Contract_ID int NOT NULL
	, Payment_ID int NOT NULL
	, Doc_ID int NOT NULL
	, CONSTRAINT Payment_fk FOREIGN KEY (Contract_ID, Payment_ID) REFERENCES Payment (Contract_ID, ID)
	, CONSTRAINT Doc_fk FOREIGN KEY (Contract_ID, Doc_ID) REFERENCES Doc (Contract_ID, ID)
	, PRIMARY KEY (Payment_ID, Doc_ID)
)
Впрочем, если уж MS Access обладает такими впечатляющими возможностями, как подзапросы в CHECK и миграция на "взрослые" СУБД не ожидается в принципе(не все из них позволяют такой "фокус", да и неизвестно, как это скажется на производительности, лучше проверить), то наверное действительно можно остановиться на варианте, предложенным Restavraciya.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36094622
Фотография Restavraciya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator Arepo,

Не забудь установить "птичку" Синтаксис для SQL Server ANSI-92 (Сервис - Параметры - Таблицы и запросы)
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095137
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем спасибо, пока остановился на внешнем ключе: добавил все-таки (не хотелось, т.к. казался избыточным) столбец Contract_nbr в таблицу Payments_docs, добавил по уникальному индексу в таблицы Docs и Payments на Doc_nbr, Contract_nbr и Payment_nbr, Contract_nbr и сделал на них ссылки. Т.е.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
create table Payments_docs (
    payment_nbr nvarchar( 20 ) not null,
    doc_nbr nvarchar( 20 ) not null,
    contract_nbr nvarchar( 20 ) not null
    allocation_amount money not null, 
    primary key (Payment_nbr, doc_nbr),
    constraint Payments_docs_docs_fk foreign key (payment_nbr, contract_nbr) references docs (doc_nbr, contract_nbr),
    contstraint Payments_docs_payments_fk foreign key (doc_nbr, contract_nbr) references payments (payment_nbr, contract_nbr)
)

Как-то оно прозрачнее, чем CHECK.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095279
Фотография Restavraciya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прошения за тупость - а как вы его (Contract_nbr) в крос таблицу загоняете ?
Не иначе как клиентом .. ? Танец живота под бубен ?

Просвятите - может и мне вкусно будет
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095385
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RestavraciyaПрошу прошения за тупость - а как вы его (Contract_nbr) в крос таблицу загоняете ?
Не иначе как клиентом .. ? Танец живота под бубен ?

Просвятите - может и мне вкусно будет
Пока никак. Придется клиентом - так что вкусно не будет
Поэтому и не хотел - все-таки вроде как денормализация - причем на начальном этапе.
То ли я чего перемудрил.... То ли недомудрил... То ли это не денормализация...
Окончательно еще не решил.
Твой CHECK до конца еще не проверил.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095472
Фотография Restavraciya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Даже больше - CHECK в JET-SQL позволяет использовать public function
А уж в ней ты можешь проверить хоть расположение звезд ;-)
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095474
Фотография Restavraciya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RestavraciyaДаже больше - CHECK в JET-SQL позволяет использовать public function
А уж в ней ты можешь проверить хоть расположение звезд ;-)... (с) Бенедикт (по сути предмета)
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095815
вроде как денормализация
Ну да. В Payments_docs нарушение 2НФ выходит. Contract_nbr ведь от атрибутов payment_nbr, doc_nbr по отдельности зависит. Не очень удачно.
А какие могут быть платежные документы, что между документами и платежами связь 'многие-ко-многим'? Может, стоит вообще как-нибудь по-другому сущности выделить?
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36095985
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Золотая рыбкаА какие могут быть платежные документы, что между документами и платежами связь 'многие-ко-многим'? Может, стоит вообще как-нибудь по-другому сущности выделить?

тиипичная организационно-финансово-налогово-бухгалтерская проблема

у одного заказчика несколько договоров, и платить он умудряется одной платёжкой по нескольким договорам
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096025
olzhas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Sator Arepo,

А зачем вообще нужна таблица Payments_docs? Можно просто давить нужные поля в Contracts, либо создать еще одну таблицу которая будет отношением многие к одному к таблице Contracts (ну это для того чтобы не были пустые поля)
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096026
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойЗолотая рыбкаА какие могут быть платежные документы, что между документами и платежами связь 'многие-ко-многим'? Может, стоит вообще как-нибудь по-другому сущности выделить?

тиипичная организационно-финансово-налогово-бухгалтерская проблема

у одного заказчика несколько договоров, и платить он умудряется одной платёжкой по нескольким договорам
Даже само собой. Но, ведь и одному документу (не договору) могут соответствовать несколько платежей и один платеж может быть распределен на несколько документов - и при все это может быть в рамках одного договора. Так что многие-ко-многим здесь нужны даже без учета разгильдяйства. ИМХО.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096035
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
olzhasSator Arepo,

А зачем вообще нужна таблица Payments_docs? Можно просто давить нужные поля в Contracts, либо создать еще одну таблицу которая будет отношением многие к одному к таблице Contracts (ну это для того чтобы не были пустые поля)
Как-то пока не догоняю. Может быть схемкой/скриптом объясните?
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096036
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator ArepoТак что многие-ко-многим здесь нужны даже без учета разгильдяйства.

Я в курсе. Это я Золотой рыбке в качестве примера пытался показать...
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096065
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойSator ArepoТак что многие-ко-многим здесь нужны даже без учета разгильдяйства.

Я в курсе. Это я Золотой рыбке в качестве примера пытался показать...
Да это я скорее себя пытался еще раз убедить... А то вдруг действительно многие-ко-многим излишество
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096129
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Золотая рыбкавроде как денормализация
В Payments_docs нарушение 2НФ выходит. Contract_nbr ведь от атрибутов payment_nbr, doc_nbr по отдельности зависит.+1. Неключевой атрибут зависит только от части любого из возможных ключей. Поэтому Contract_nbr должен входить в состав ключа, чтобы всё было по честному. Но тогда, чисто формально, мигрировать должны составные ключи, уникальность которых, в данном случае, определяется обоими полями, а не одним из них. Т.е., уникальность payment_nbr или doc_nbr должна обеспечиваться только в комбинации с Contract_nbr. К сожалению, это не так, потому что и payment_nbr и doc_nbr в "родных" таблицах явно подразумеваются "уникальными", т.е., простыми ключами. Таким образом в эти таблицы должны быть введены поля, характеризующие уникальность только в рамках контракта, в результате чего появится новый, составной, ключ, который и должен будет мигрировать в таблицу Payments_docs. В этом случае, нарушения 2NF будет устранено.
С другой стороны, чисто в практических целях иногда можно пренебречь некоторыми принципами, чтобы получить нужное ограничение. В данном случае серьёзных последствий от такого нарушения не будет, IMHO.

P.S. Лично я попытался бы пойти по первому пути, т.е., поиска уникальности в рамках контракта.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096142
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChAЗолотая рыбкавроде как денормализация
В Payments_docs нарушение 2НФ выходит. Contract_nbr ведь от атрибутов payment_nbr, doc_nbr по отдельности зависит.+1. Неключевой атрибут зависит только от части любого из возможных ключей. Поэтому Contract_nbr должен входить в состав ключа, чтобы всё было по честному. Но тогда, чисто формально, мигрировать должны составные ключи, уникальность которых, в данном случае, определяется обоими полями, а не одним из них. Т.е., уникальность payment_nbr или doc_nbr должна обеспечиваться только в комбинации с Contract_nbr. К сожалению, это не так, потому что и payment_nbr и doc_nbr в "родных" таблицах явно подразумеваются "уникальными", т.е., простыми ключами. Таким образом в эти таблицы должны быть введены поля, характеризующие уникальность только в рамках контракта, в результате чего появится новый, составной, ключ, который и должен будет мигрировать в таблицу Payments_docs. В этом случае, нарушения 2NF будет устранено.
С другой стороны, чисто в практических целях иногда можно пренебречь некоторыми принципами, чтобы получить нужное ограничение. В данном случае серьёзных последствий от такого нарушения не будет, IMHO.

P.S. Лично я попытался бы пойти по первому пути, т.е., поиска уникальности в рамках контракта.
Т.е. CHECK? Или что?
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096231
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator ArepoТ.е. CHECK? Или что?Собственно, простейший вариант здесь . В таблицах Payment и Doc поле ID не считается уникальным, уникальны только их комбинации с Contract_ID (см. PRIMARY KEY). Т.е., ID это как бы номер оплаты или документа в рамках одного контракта и для разных Contract_ID значение ID запросто может повторяться. Поле ID можно заменить на любое другое, лишь бы его уникальность подразумевалась в рамках контракта. Ну, например, дата оплаты или получения документа. Возможно в полях Payment_nbr или Doc_nbr подразумевается контракт и состоит из пары частей типа ("Контракт №" + "№ документа по контракту"), тогда из него можно удалить "Контракт №", оставив часть "№ документа по контракту", которая будет уникальна только в комбинации с Contract_ID.
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096237
Фотография ChA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Исправляю ссылку .
...
Рейтинг: 0 / 0
констрейнт на таблицу
    #36096244
АнатоЛойу одного заказчика несколько договоров, и платить он умудряется одной платёжкой по нескольким договорам
Sator Arepoодному документу (не договору) могут соответствовать несколько платежей и один платеж может быть распределен на несколько документов - и при все это может быть в рамках одного договора
Да, Вы правы. Я уже забыла, как платежное поручение выглядит... давно его не видела.
Так с учетом вышесказанного как вариант:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
CREATE TABLE Contract (
	ID int PRIMARY KEY
	, Contract_nbr nvarchar( 20 ) NOT NULL UNIQUE
	, Company_id int NOT NULL REFERENCES Company (ID)
)

CREATE TABLE Payment (
	, ID int NOT NULL PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, UNIQUE (Contract_ID, ID)
)

CREATE TABLE Doc (
	, ID int NOT NULL PRIMARY KEY
	, Name nvarchar( 20 ) NOT NULL UNIQUE
	, Amount money NOT NULL
	, UNIQUE (Contract_ID, ID)
)

CREATE TABLE PayDetails (
	Contract_ID int NOT NULL
	, Payment_ID int NOT NULL
	, Doc_ID int NOT NULL
	, CONSTRAINT Payment_fk FOREIGN KEY ( Payment_ID) REFERENCES Payment (ID)
	, CONSTRAINT Doc_fk FOREIGN KEY (Doc_ID) REFERENCES Doc (ID)
        , CONSTRAINT Contract_fk FOREIGN KEY (Contract_ID) REFERENCES Doc (ID)
	, PRIMARY KEY (Payment_ID, Doc_ID,Contract_ID )
)
где PayDetails - ассоциативная таблица
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / констрейнт на таблицу
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]