GreenStone90


Hi,

I'm trying to figure out how to setup a Constraint (Foreign Key ) from a lookup table.

For the following example, I want to constrain to constrain so that a Car.ParkingSpotNumber is unique for a given ParkingFacility.

Any thoughts

Thanks!

Andy

Here's the scenario:

CAR table:

Id (PrimaryKey)

LicensePlateNumber

ParkingSpotNumber

PARKINGFACILITY__CAR__LOOKUP table:

Id (PrimaryKey)

CarId (Foreign Key to Car.Id)

ParkingFacilityId (Foreign Key to ParkingFacility)

PARKINGFACILITY table:

Id (PrimaryKey)

PARKINGLOT table:

Id (Foreign Key to ParkingFacility.Id) (PrimaryKey)

Address

PARKINGGARAGE table:

Id (Foreign Key to ParkingFacility.Id) (PrimaryKey)

Address

Here's the T-SQL code to make a SQLServer2005 database for this scenario:

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Car]') AND type in (N'U'))

BEGIN

CREATE TABLE [dbo].[Car](

[Id] [bigint] NOT NULL,

[CustomerName] [nvarchar](50) NOT NULL,

[ParkingSpotNumber] [int] NOT NULL,

CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED

(

[Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

END

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ParkingFacility]') AND type in (N'U'))

BEGIN

CREATE TABLE [dbo].[ParkingFacility](

[Id] [bigint] NOT NULL,

CONSTRAINT [PK_ParkingFacility] PRIMARY KEY CLUSTERED

(

[Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

END

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ParkingFacility__To__Car_Lookup]') AND type in (N'U'))

BEGIN

CREATE TABLE [dbo].[ParkingFacility__To__Car_Lookup](

[Id] [bigint] NOT NULL,

[CarId] [bigint] NOT NULL,

[ParkingFacilityId] [bigint] NOT NULL,

CONSTRAINT [PK_ParkingFacility__To__Car_Lookup] PRIMARY KEY CLUSTERED

(

[Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

END

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ParkingLot]') AND type in (N'U'))

BEGIN

CREATE TABLE [dbo].[ParkingLot](

[Id] [bigint] NOT NULL,

[Address] [nvarchar](50) NOT NULL,

CONSTRAINT [PK_ParkingLot] PRIMARY KEY CLUSTERED

(

[Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

END

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ParkingGarage]') AND type in (N'U'))

BEGIN

CREATE TABLE [dbo].[ParkingGarage](

[Id] [bigint] NOT NULL,

[Address] [nvarchar](50) NOT NULL,

CONSTRAINT [PK_ParkingGarage] PRIMARY KEY CLUSTERED

(

[Id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

END

GO

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ParkingFacility__To__Car_Lookup_Car]') AND parent_object_id = OBJECT_ID(N'[dbo].[ParkingFacility__To__Car_Lookup]'))

ALTER TABLE [dbo].[ParkingFacility__To__Car_Lookup] WITH CHECK ADD CONSTRAINT [FK_ParkingFacility__To__Car_Lookup_Car] FOREIGN KEY([CarId])

REFERENCES [dbo].[Car] ([Id])

GO

ALTER TABLE [dbo].[ParkingFacility__To__Car_Lookup] CHECK CONSTRAINT [FK_ParkingFacility__To__Car_Lookup_Car]

GO

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ParkingFacility__To__Car_Lookup_ParkingFacility]') AND parent_object_id = OBJECT_ID(N'[dbo].[ParkingFacility__To__Car_Lookup]'))

ALTER TABLE [dbo].[ParkingFacility__To__Car_Lookup] WITH CHECK ADD CONSTRAINT [FK_ParkingFacility__To__Car_Lookup_ParkingFacility] FOREIGN KEY([ParkingFacilityId])

REFERENCES [dbo].[ParkingFacility] ([Id])

GO

ALTER TABLE [dbo].[ParkingFacility__To__Car_Lookup] CHECK CONSTRAINT [FK_ParkingFacility__To__Car_Lookup_ParkingFacility]

GO

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ParkingLot_ParkingFacility]') AND parent_object_id = OBJECT_ID(N'[dbo].[ParkingLot]'))

ALTER TABLE [dbo].[ParkingLot] WITH CHECK ADD CONSTRAINT [FK_ParkingLot_ParkingFacility] FOREIGN KEY([Id])

REFERENCES [dbo].[ParkingFacility] ([Id])

GO

ALTER TABLE [dbo].[ParkingLot] CHECK CONSTRAINT [FK_ParkingLot_ParkingFacility]

GO

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ParkingGarage_ParkingFacility]') AND parent_object_id = OBJECT_ID(N'[dbo].[ParkingGarage]'))

ALTER TABLE [dbo].[ParkingGarage] WITH CHECK ADD CONSTRAINT [FK_ParkingGarage_ParkingFacility] FOREIGN KEY([Id])

REFERENCES [dbo].[ParkingFacility] ([Id])

GO

ALTER TABLE [dbo].[ParkingGarage] CHECK CONSTRAINT [FK_ParkingGarage_ParkingFacility]




Re: ForeignKey Constraint from a Lookup Table

Arnie Rowland


A parking spot belongs to a facility, a facility can't have duplicate spots.

Seems the facility table 'should' have a row for each parking spot, and the FacilityID, ParkingSpotID becomes the PK.

Think in terms of what is the 'product' being sold. You are selling a 'spot', therefore a 'spot' needs to be tracked.

The way you have it outlined would be like a grocery store carring Vendors, and the actual Product sold is assigned to the Customer -but it is not carried in a Products table.

And I would think that a car 'could' be assigned to multiple spots (albeit different facilities), and that a 'spot' could have multiple cars assigned (carpool, spouse's car, different days/times/shifts, etc).

My suggested variation:

CarOwner

ID IDENTITY

Name

Address

Phone

etc...

CAR

Id IDENTITY (PrimaryKey)

LicensePlateNumber

Make/Model/Color/etc

CarOwner.ID

Facility

ID IDENTITY (PrimaryKey)

Address

FacilityType (Garage/Lot/Etc)

etc...

ParkingSpot

ID IDENTITY (PrimaryKey)

Facility.ID

ParkingSpot (Physical Location Identifier)

UNIQUE (Facility.ID, ParkingSpot )

CarParkingSpot

ID IDENTITY (PrimaryKey)

Car.ID (Foreign Key to Car.Id)

ParkingSpots.ID (Foreign Key to ParkingSpots)

Just a 'rough' idea -but I hope you will see that it becomes easier to manage your inventory of spots. If you leased a 'spot' to multiple users and for different times, you may need a scheduling table.







Re: ForeignKey Constraint from a Lookup Table

GreenStone90

Hi Arnie,

Thanks for the quick reply!

Yes, from what I stated was the problem, I like your re-think on things better.

However, another twist (which I forgot to mention):

In a few facilities (with valet parking) a given car may be parked, but not in a parking spot (amazing how those valet parking guys can create spots from nothing).

So if a car is in a "real" parking spot (that has a number), then the facility/parkingspot has to be unique. However, if a car is in a "made up" parking spot (i.e. the parking spot number is null in the database), then such a "uniqueness" constraint is not-applicable.

Thanks for you help!

Andy






Re: ForeignKey Constraint from a Lookup Table

Arnie Rowland

I totally understand about the 'phantom' parking spots.

It may be appropriate to have some number of 'spots' that don't have a physical location. Sort of like a theatre selling SRO tickets. (Standing Room Only). They still have a 'ticket', the ticket has a number -it just doens't correspond with a 'spot' (seat).

For each location you may benefit from some number of SRO 'spots'. Locations: X-1, X-2, etc.

Now about those valets. Actually, they aren't creating 'spots from nothing', they are shuffling around the cars. Some guy drives up with a nice Ferrari and voila, it 'finds' a spot -even if that means one of the valets has to drive it around until a 'real' spot opens up. They are known to 'go the extra mile' for customers...

Wink