Apply a not null constraint via a many-to-many relationship? - sql

I need to make sure that every project in my database has a contact person. "projects" and "contacts" have a many-to-many relationship, specified in the table "projects_contacts". Could I create a table constraint within projects that will specify the project must exist within the join table? Or do I need to take a completely different approach?
(I need users to be able to manually enter contact data while in the middle of adding project data, so I'm worried that the NOT NULL will hang up their ability to create a project before there is a contact.)
Would this be better addressed in the build of the user interface?
Thanks!
CREATE TABLE projects(
id_project INTEGER PRIMARY KEY,
description text)
CREATE TABLE contacts(
id_contact integer PRIMARY KEY
firstname varchar(100) )
CREATE TABLE projects_contacts(
id_projects_contacts integer PRIMARY KEY,>
id_project integer,
id_contact integer
CONSTRAINT FOREIGN KEY project_fkey (id_project) REFERENCES projects ON UPDATE CASCADE ON DELETE CASCADE
CONSTRAINT FOREIGN KEY contact_fkey (id_contact) REFERENCES contacts ON UPDATE CASCADE ON DELETE CASCADE)

The only way you could implement this with a table-level constraint is for projects to contain a non-nullable foreign key reference to any entry in projects_contacts.
But this would be a circular reference, since projects_contacts also depends on `projects.
You said you don't want to force users to enter a contact while they're still creating a project, so basically you can't constrain a project with a non-nullable reference like that.
There is no constraint that means "I need this to be non-null, but later." It's in the definition of any constraint that it must be satisfied by the time you end the transaction.
Therefore most you can defer a constraint is until commit:
http://www.postgresql.org/docs/9.3/static/sql-set-constraints.html
I assume you will need the deferral to be longer than the length of one transaction.
So ultimately, these types of custom business rules end up being enforced by application code that you have to develop.

If including a contact on the project is mandatory, then your GUI should not send an add request unless the contact data (or key if already exists) is part of the transaction.
This way, you don't need the FK to allow nulls.
However, from business standpoint, what would you do when a contact is no longer a contact for the project and no substitute contact has been assigned?
In this case, your business should make the decision. If so, the FK has to allow nulls on update.
To combine both cases, your FK should allow nulls but your business layer should not accept create project transaction with null contact fk.
You also need to think about this business question: Could a contact exist without a project? The answer is important in your GUI design.
As per your statement "I need users to be able to manually enter contact data while in the middle of adding project data" - This makes sense to me only if the contacts would be directly added to the current project, but what if the user starts creating a project, create a contact then abandons the process of creating the project? How would you identify the added contact? So, may be you want to refine this requirement.

Related

Logical Modeling difficulty

I have a task to design a simple database that will store information about restaurants, customers and Categories that each restorant falls in (ex. American,Indian...). The problem is that I am not sure how to model the database having the fact that every customer may have zero or more registered other
customers as friends. Whilst a customer can have many friend connections, for
each friend connection the date must be recorded.
I assume that I have to create another table called Friends that will contain the cust_id,data as attributes.
My tables are:
Restaurants(rest_id,name,address,date_opened,income_cat_id*)
Category(car_id,title,Description)
Customers(cust_id,name,address,DOB,Mobile_number)
Here is my ER Diagram, but as I said I am not sure if the Recursive relation is right for my Customers table:
Yes, you need another table to model the connections, something like:
Connection(cust_id1, cust_id2, connectdate)
Thank you a very much!
Does that mean that I have to have the following constraints in the Connection table?
CONSTRAINT pk_Connections PRIMARY KEY (cust_id1,cust_id2),
CONSTRAINT fk_Customers_Connections_cust_id1 FOREIGN KEY (cust_id1) REFERENCES Customers(cust_id)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_Customers_Connections_cust_id2 FOREIGN KEY (cust_id2) REFERENCES Customers(cust_id)
ON DELETE NO ACTION ON UPDATE NO ACTION);

SQL What is the Purpose of 1 to 1 self reference on primary key? [duplicate]

I went over a legacy database and found a couple of foreign keys that reference a column to itself. The referenced column is the primary key column.
ALTER TABLE [SchemaName].[TableName] WITH CHECK ADD
CONSTRAINT [FK_TableName_TableName] FOREIGN KEY([Id])
REFERENCES [SchemaName].[TableName] ([Id])
What is the meaning of it?
ALTER TABLE [SchemaName].[TableName] WITH CHECK ADD
CONSTRAINT [FK_TableName_TableName] FOREIGN KEY([Id])
REFERENCES [SchemaName].[TableName] ([Id])
This foreign key is completely redundant and pointless just delete it. It can never be violated as a row matches itself validating the constraint.
In a hierarchical table the relationship would be between two different columns (e.g. Id and ParentId)
As for why it may have been created quite likely through use of the visual designer if you right click the "Keys" node in object explorer and choose "New Foreign Key" then close the dialogue box without deleting the created foreign key and then make some other changes in the opened table designer and save it will create this sort of redundant constraint.
In some cases this is a preferred way to reduce redundancy in your model. In using the self referencing foreign key (as shown in you example) you create a hierarchical relationship between rows in your table. Pay attention to what happens when you delete a row from the table, cascading on delete might remove rows you still want.
Using these sort of keys moves some of the data validation to the DB model as opposed to making this a responsibility of the program/programmer. Some outfits prefer this way of doing things. I prefer to make sure programs and programmers are responsible - data models can be hard to refactor and upgrade in production environments.

How to get all references which hinders delete of a row I'm trying to delete

I have an Sql-Server database (2008R2, if that is important) with lots of tables.
Some table contains foreign key references to other tables, and some of the foreign key constraints have cascade on delete, and some are restricted delete.
To be user friendly, in my application I want to figure out all other references that needs to be deleted before I can delete the one I'm currently deleting and present it to the user.
Some generic problems described below:
I try to delete from Customer where Id = 1 and Order has a foreign key to Customer (and that foreign key restricts user from deleting customer before orders are deleted), I would want to get a result of all Orders that restricts me from deleting Customer.
If Contracts have references to Customer as well, and that foreign key is cascade, but Contract is referenced by Alarm with restricted delete, I want to get which Contract was responsible for not being able to delete Customer, and also the Alarms which was responsible for not being able to delete Customer.
I want this behavior to be recursive, so that I get all connections, direct or indirect which hindered me from deleting Customer in the first place. I also want to be able to get this information wherever I start (No matter if I wanted to delete a Customer, Order, Alarm etc)
It feels like someone aught to have had similar problems before me, but I can mostly find information to get table->table foreign key restrictions, not in relation to a specific entity in the database (i.e. customer with Id = 1)
Is there any simple way of doing this?
basically I look at this as part of database/application architecture and you need to know as the developer or DBA how you tables are connected.
You need to use the customer ID and query against any table that uses customerID as a foreign key and that would give you a result.same with the contracts. You can do this with some ERD tools, but I tend to make my own classes to do this for my databases, this way I have total control of what I want to do. For instance in the delete method for a customer, a company may just want to disable or set active to false for the customer. or truly delete everything.
There is a way to cascade deletion in the database, but I am not sure you want to do that, since you are asking for a result to be returned.

What's a foreign key for?

I've been using table associations with SQL (MySQL) and Rails without a problem, and I've never needed to specify a foreign key constraint.
I just add a table_id column in the belongs_to table, and everything works just fine.
So what am I missing? What's the point of using the foreign key clause in MySQL or other RDBMS?
Thanks.
A foreign key is a referential constraint between two tables
The reason foreign key constraints exist is to guarantee that the referenced rows exist.
The foreign key identifies a column or set of columns in one (referencing or child) table that refers to a column or set of columns in another (referenced or parent) table.
you can get nice "on delete cascade" behavior, automatically cleaning up tables
There are lots of reason of using foreign key listed over here: Why Should one use foreign keys
Rails (ActiveRecord more specifically) auto-guesses the foreign key for you.
... By default this is guessed to be the name of the association with an “_id” suffix.
Foreign keys enforce referential integrity.
Foreign key: A column or set of columns in a table whose values are required to match at least one PrimaryKey values of a row of another table.
See also:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
http://c2.com/cgi/wiki?ForeignKey
The basic idea of foreign keys, or any referential constraint, is that the database should not allow you to store obviously invalid data. It is a core component of data consistency, one of the ACID rules.
If your data model says that you can have multiple phone numbers associated with an account, you can define the phone table to require a valid account number. It's therefore impossible to store orphaned phone records because you cannot insert a row in the phone table without a valid account number, and you can't delete an account without first deleting the phone numbers. If the field is birthdate, you might enforce a constraint that the date be prior to tomorrow's date. If the field is height, you might enforce that the distance be between 30 and 4000 cm. This means that it is impossible for any application to store invalid data in the database.
"Well, why can'd I just write all that into my application?" you ask. For a single-application database, you can. However, any business with a non-trivial database that stores data used business operations will want to access data directly. They'll want to be able to import data from finance or HR, or export addresses to sales, or create application user accounts by importing them from Active Directory, etc. For a non-trivial application, the user's data is what's important, and that's what they will want to access. At some point, they will want to access their data without your application code getting in the way. This is the real power and strength of an RDMBS, and it's what makes system integration possible.
However, if all your rules are stored in the application, then your users will need to be extremely careful about how they manipulate their database, lest they cause the application to implode. If you specify relational constraints and referential integrity, you require that other applications modify the data in a way that makes sense to any application that's going to use it. The logic is tied to the data (where it belongs) rather than the application.
Note that MySQL is absolute balls with respect to referential integrity. It will tend to silently succeed rather than throw errors, usually by inserting obviously invalid values like a datetime of today when you try to insert a null date into a datetime field with the constraint not null default null. There's a good reason that DBAs say that MySQL is a joke.
Foreign keys enforce referential integrity. Foreign key constraint will prevent you or any other user from adding incorrect records by mistake in the table. It makes sure that the Data (ID) being entered in the foreign key does exists in the reference table. If some buggy client code tries to insert incorrect data then in case of foreign key constraint an exception will raise, otherwise if the constraint is absent then your database will end up with inconsistent data.
Some advantages of using foreign key I can think of:
Make data consistent among tables, prevent having bad data( e.g. table A has some records refer to something does not exist in table B)
Help to document our database
Some framework is based on foreign keys to generate domain model

Constrain table entries on sql table

I have 3 related tables as shown in the image below.
Everyone has an entry in the User table and a UserRole.
Some Users are Subscribers.
I want to constrain the Subscribers table so that it can only contain users whose role IsSusbcriber but retain the UserRole at User level. Is it possible?
Excuse the current relationships between the table, they represent whats there at the moment rather whats necessarily needed.
I think you could drop the IsSubscriber columns and add a UserSubscriberRoles table that will contain exactly those roles that had previously set the IsSubscriber column.
CREATE UserSubscriberRoles
( UserRoleId PRIMARY KEY
, FOREIGN KEY (UserRoleId)
REFERENCES UserRoles (UserRoleId)
) ;
Then change the FKs in Subscribers table to:
FOREIGN KEY (UserId, UserRoleId)
REFERENCES User (UserId, UserRoleId)
FOREIGN KEY (UserRoleId)
REFERENCES UserSubscriberRoles (UserRoleId)
Is it possible?
In theory, yes; you can use a SQL assertion. See this StackOverflow answer for an example.
In practice, however, no major DBMS supports SQL assertions, and what you describe cannot be implemented as a foreign-key constraint, so I think your only option is to write a trigger that evaluates this constraint, and raises an exception if it's not satisfied.
The only way to contrain this without RoleId in the table is via either a trigger (and triggers are usually a bad design choice), or a SQL Agent job that periodically removes people from Subscribers that don't fit the criteria.
With RoleID in Subscribers, you can add a check constraint that limits it to a specific value.
This would really be better enforced with a different design and/or in the application code.