I have a table called cars and one called roads
Roads: Cars:
Name Road_Id Owner Car_Id
------------------- ---------------------
roade45 1 Hugo 1
roade20 2 Eson 2
roade10 3 Karl 3
I need to create an N:M relation between these (one can can drive on many roads, one road can have many cars).
It is a dumb example, but it needs to be an N:M relation.
I do this relation by creating an other table called cars_roads with these columns
Road_id | Car_id | uniqueValue
My problem is now that I have no idea on how to get the uniqueValue to take form, this value will be used to prevent doubles from occurring, eg. the same car is added to the same road a second time.
My table is created using this code:
CREATE TABLE [dbo].[Tbl_cars_roads]
(
[Road_id] INT NOT NULL,
[car_id] INT NOT NULL,
CONSTRAINT [PK_Tbl_Road_id] FOREIGN KEY ([Road_id]) REFERENCES [dbo].[Tbl_Cars] ([Road_id]),
CONSTRAINT [PK_Tbl_car_id] FOREIGN KEY ([car_id]) REFERENCES [dbo].[Tbl_Roads] ([car_id])
)
How can I add an uniqueValue key and make it work as explained to this code?
This should make unique group you want.
CONSTRAINT [UQ_CarRoads] UNIQUE NONCLUSTERED
(
[Road_id] ASC,
[car_id] ASC
)
Just add the following code after your last constraint:
CONSTRAINT [UK_Road_Car] UNIQUE ([Road_id], [car_id])
Related
Project summary
We're creating a 'digital' kitchen where it's possible to add which items are in your fridge, freezer etc. Then it's possible to view these items on a webapplication, so you know groceries you have in your kitchen on the go.
The database
In total there are three tables.
Lists
This holds ListIDs and names of these Lists, like 'Fridge' or 'Freezer'. So, this is basically the 'container'.
Items
Then there's Items which holds itemtypes, i.e. Milk, 1 gallon.
ListItems
Then there's ListItems (sorry for a slightly confusing name) which holds specific items. While Items is just a table of items which can be added, ListItems are the added items. So the rows added to this table naturally have a foreign key to both a List on the Lists table and a foreign key to an Item on the Items table. This table's primary key is a superkey, made from nearly all its attributes.
Two ListItems can refer to the same Item and same List, as long as they have different attributes. They could expire on different dates or be different unit sizes. The only thing that makes an Item unique is the name, like if you added a 'Ham', it would never overwrite a 'Milk'. Adding another 'Milk' would then be seen as the same Item
The Problem
Here's an example. You want to add two seperate items. The first is 3 hams, each 200 g which expire on the 28th of May.
The next is another ham, this one single, but 500g and expires on the 31st of May:
ListID 1 refers to the List which is called Fridge.
ItemID 1 refers to the item which is called Ham.
See the problem? The foreign keys are the same.
It stores just fine on our local database but when syncing with an Azure database, we get the following error:
{"Violation of PRIMARY KEY constraint 'PK__#A4D1762__44A4C03D49E5E4B8'.
Cannot insert duplicate key in object 'dbo.#changeTable'.
The duplicate key value is (1, 1).\r\n
The data for table-valued parameter \"#changeTable\" doesn't conform to the table type of the parameter.
SQL Server error is: 3602, state: 30\r\nThe statement has been terminated."}
Is this poor database design or an Azure problem?
Update 1
Here's how the DDL looks on the local database:
CREATE TABLE [dbo].[ListItems] (
[ListId] INT NOT NULL,
[ItemId] INT NOT NULL,
[Amount] INT NOT NULL,
[Volume] INT NOT NULL,
[Unit] NVARCHAR(MAX) NULL,
[ShelfLife] DATETIME NOT NULL,
CONSTRAINT [pk_ListItems] PRIMARY KEY CLUSTERED ([ShelfLife], [Volume], [Amount], [ItemId], [ListId]),
CONSTRAINT [fk_ListItems] FOREIGN KEY ([ListId]) REFERENCES [dbo].[Lists] ([ListId]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [fk_ListItems2] FOREIGN KEY ([ItemId]) REFERENCES [dbo].[Items] ([ItemId]) ON DELETE CASCADE ON UPDATE CASCADE
);
And the Azure database DDL:
CREATE TABLE [dbo].[ListItems] (
[ListId] INT NOT NULL,
[ItemId] INT NOT NULL,
[Amount] INT NOT NULL,
[Volume] INT NOT NULL,
[Unit] NVARCHAR (MAX) NULL,
[ShelfLife] DATETIME NOT NULL,
CONSTRAINT [PK_dbo.ListItems] PRIMARY KEY CLUSTERED ([ListId] ASC, [ItemId] ASC, [Amount] ASC, [Volume] ASC, [ShelfLife] ASC),
CONSTRAINT [FK_dbo.ListItems_dbo.Items_ItemId] FOREIGN KEY ([ItemId]) REFERENCES [dbo].[Items] ([ItemId]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.ListItems_dbo.Lists_ListId] FOREIGN KEY ([ListId]) REFERENCES [dbo].[Lists] ([ListId]) ON DELETE CASCADE
);
The PK CONSTRAINT line is slightly different, but the attributes are the same. Could this be the problem?
I don't think the error is where you think it is. If the PK on the local and Azure ListItems both name the same columns (irrespective of order), they are the same. The error message, however, mentions a different PK definition (and a different tablename):
Violation of PRIMARY KEY constraint 'PK__#A4D1762__44A4C03D49E5E4B8'.
Cannot insert duplicate key in object 'dbo.#changeTable'.
The duplicate key value is (1, 1).
There appears to be a table whose name is "#changetable" -- which looks like a store procedure parameter to me -- that is defined with a two-column primary key. Track it down and you'll solve the problem.
I know it's first std question but someone asked me, but i was unable give him apropriate answer.
There are two tables Employee,Technology having many to many relation saved in employee_technology_rel.Employee table having fields- emp_id (auto_increment),emp_name(varchar),DOB (date) where Technology having fields tech_id(auto_increment),tech_name(varchar)
these two tables allows duplication of names.which unique constraint should i define for allowing unique entry?
You can define the unique entry on table employee_technology_rel,
ALTER TABLE employee_technology_rel
ADD CONSTRAINT emptech_pk PRIMARY KEY (emp_id, tech_id)
// or if you have set a primary key already, you can still define via UNIQUE
ALTER TABLE employee_technology_rel
ADD CONSTRAINT emptech_uq UNIQUE (emp_id, tech_id)
what it does is it only allows unique technology for every employee.
in order for you to have unique emp_name on table Employee as well as unique tech_name on table Technology, you can also alter the table by adding unique constraint
ALTER TABLE Employee ADD CONSTRAINT emp_uq UNIQUE (emp_name)
ALTER TABLE Technology ADD CONSTRAINT tech_uq UNIQUE (tech_name)
You want a composite primary key defined on the two columns in employee_technology_rel: emp_id and tech_id.
Unique Index and Unique Constraint are the same. They achieve same
goal. SQL Performance is same for both.
Add Unique Constraint
ALTER TABLE dbo. ADD CONSTRAINT
UNIQUE NONCLUSTERED ( ) ON
[PRIMARY]
Add Unique Index
CREATE UNIQUE NONCLUSTERED INDEX
ON dbo. ( ) ON
[PRIMARY]
Source sqlauthority.com and msdn from Google search: "SQL server unique index".
Is there a way for me to create only one foreign key in one table that refers to 2 different fields in that same table
example:
table: family
ID | bird | bird_mom | bird_dad
1___X_____2_______3
2____A____4________5
3____B
4____M
5____N
ID is primary and autoincrement and also foreign key for "bird_mom" and "bird_dad" field.
So when I change entries X,A,B,M,N I dont need to change it everywhere, but it will always be recognized by foreign key-ID
Typically, "foreign key" is the name for the child field that points to the parent, so you would have two foreign keys:
CREATE TABLE family (
ID INTEGER PRIMARY KEY,
bird TEXT,
bird_mom INTEGER REFERENCES family(ID),
bird_dad INTEGER REFERENCES family(ID)
)
I have two tables:
CREATE TABLE Order (
orderId INTEGER IDENTITY NOT NULL,
PRIMARY KEY (orderId)
)
CREATE TABLE OrderAdditionalDetails (
additionalDetailsId INTEGER IDENTITY NOT NULL,
orderId INTEGER NOT NULL,
PRIMARY KEY (additionalDetailsId),
FOREIGN KEY (orderId) REFERENCES Order(orderId)
)
I have a Foreign key (FK_OrderAdditionalDetails_Order) declared on the OrderAdditionalDetails table, on the orderId field. I also have a 'unique' constraint on the orderId field in the OrderAdditionalDetails table. The idea is that each 'order' will have zero or one entries in the 'OrderAdditionalDetails' table.
This all picked up by the entity framework model file, however when I try to create the Navigation property, it only lets me declare a 1 to many relationship. The error I get is as follows:
Running transformation: Multiplicity is not valid in Role 'OrderAdditionalDetails' in relationship 'FK_OrderAdditionalDetails_Order'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be *.
I'm really not sure what this means - googling the error did not prove helpful. Can anybody shed some light on what I am doing wrong?
In your OrderAdditionalDetails table, remove the additionalDetailsID column and make the orderID the CLUSTERED PRIMARY KEY. Keep the FOREIGN KEY you already have. That is the right way to implement this.
There is not only no value added by the additionalDetailsId column, it makes things worse by taking more space in the table. The orderID is already a sufficient key; you need no secondary artificial key that is nothing but a surrogate for orderID.
Your Foreign Key must be defined as UNIQUE in order to enforce a One-To-Zero-Or-One relationship.
Maybe try something like this:
CREATE TABLE OrderAdditionalDetails (
additionalDetailsId INTEGER IDENTITY NOT NULL,
orderId INTEGER NOT NULL UNIQUE,
PRIMARY KEY (additionalDetailsId),
FOREIGN KEY (orderId) REFERENCES Order(orderId)
)
See Also: Implementing one-to-zero-or-one relation in SQL Server
I was trying to associate a table with a view of itself plus some other fields. (There is a very good reason for this that has nothing to do with the answer)
What cause the same error was there was more than one key field on the view. Even though I had specified the fields involved in the association it wanted both to be the only key fields for a 1 to 1 to work.
I also set the key field to be Distinct in the view, but I did that before I removed the key attribute of other fields, so it may ,or may not, be necessary.
This is likely a much broader SQL topic than Entity Framework, and I'm very much a newbie in both these arenas, but I'll ask it in terms of Entity Framework.
I would like to enforce a many-to-8 relationship. My setup is this:
A PersonGroup needs 8 (unique) Persons.
A Person can be in many different PersonGroups.
The order of the PersonGroup matters (the first needs to remain first, etc).
Easy access to all people in a PersonGroup and all PersonGroups a Person is in.
I've tried the following:
1) Add 8 1..many associations between Person and PersonGroup. I can certainly not have more than 8 Persons per group using this solution. However, to find all groups a person is in I need to iterate over 8 variables in the Person field, which is clunky.
2) Add 8 ids to PersonGroup that match up with a Person. Once again, I can guarantee only 8 persons per group, but there is no automatic link back through the association of Person->PersonGroup. I now need to be sure to add it to two places.
3) Just do a many...many relationship and handle it in code. There are two problems with this: I cannot guarantee only 8 persons per group, and I'm unsure if I can assure the order remains the same.
So, which is the best, or what solution am I missing?
An n:m relationship with a "catch":
Person
------
PersonId
PRIMARY KEY (PersonId)
PersonGroup
-----------
GroupId
PRIMARY KEY (GroupId)
Belongs
-------
GroupId
PersonId
Ordering
PRIMARY KEY (GroupId, PersonId)
FOREIGN KEY (GroupId)
REFERENCES PersonGroup (GroupId)
FOREIGN KEY (PersonId)
REFERENCES Person (PersonId) --- all normal up to here
UNIQUE KEY (GroupId, Ordering) --- the "catch"
CONSTRAINT Ordering_chk --- ensuring only up to 8 persons
CHECK Ordering IN (1,2,3,4,5,6,7,8) --- per group
You should make sure that the CHECK constraint is available in the SQL engine you'll use (MySQL for example would trick you into believing it has such constraints but it simply ignores them. SQL-Server does not return an error but happily adds a NULL in the checked column if you try to insert one.)
There is a limitation to this approach. The Ordering field has to be NOT NULL because if it is NULL, more than 8 rows (with NULL there) could be inserted (except for SQL-Server which would allow you only up to 9 rows, eight with values and one with NULL.)
To ensure maximum of 8 rows and NULLs in the Ordering, you could make a more complex constraint like the one described in MSDN site, CHECK Constraints (if your RDBMS has such feature) but I'm not at all sure on the performance of such a beast:
CREATE FUNCTION CheckMax8PersonPerGroup()
RETURNS int
AS
BEGIN
DECLARE #retval int
SELECT #retval = CASE WHEN EXISTS
( SELECT *
FROM Belongs
GROUP BY GroupId
HAVING COUNT(*) > 8
)
THEN 0
ELSE 1
END
RETURN #retval
END;
GO
ALTER TABLE Belongs
ADD CONSTRAINT Ordering_chk
CHECK (CheckMax8PersonPerGroup() = 1 );
GO
The constraint could alternatively be created as a FOREIGN KEY to a reference table with 8 rows. (If you use MySQL, that's the only way to have the equivalent of CHECK.)
A variation would be to use the (GroupId, Ordering) as the Primary Key and not have any constraint on the (GroupId, PersonId) combination. This would allow for a Person having multiple positions in a Group (but still up to 8) .
Many-to-many seems ok to me. You can easily make sure there are no more than 8 persons per group by implementing triggers. Also, you can add order column to this table if you think it's important for your logic.