2012-08-07 70 views
0

我對將多個列作爲外鍵指向單個列存在疑問。讓我用一個例子來解釋。將不同表中的多列作爲一列的外鍵

例如:我有3個表:

公司1Company_ID(guid) as Primary key, Address (varchar(25))

Company2的Company_ID(guid) as Primary key, Address (varchar(25))

員工Employee_ID(guid) as Primary key, Company_ID (Foreign key referencing from Company1 and Company2)

這裏公司的外鍵Employee表中的_ID來自2個不同的表。 這工作在SQL服務器2008.

我的問題是我不知何故覺得這是不正確的。我從來沒有在任何系統中做過這件事,但我正在嘗試這個樣本,它的工作原理。我無法解釋自己這裏有什麼不對,因爲它完美地工作。

我的假設是否正確或請引導我關於此?上述關係中的缺陷是什麼?

USE [master] 
GO 
/****** Object: Database [Test] Script Date: 08/07/2012 14:32:32 ******/ 
CREATE DATABASE [Test] ON PRIMARY 
(NAME = N'Test', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.FLEXIQUOTE\MSSQL\DATA\Test.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB) 
LOG ON 
(NAME = N'Test_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.FLEXIQUOTE\MSSQL\DATA\Test_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) 
GO 
ALTER DATABASE [Test] SET COMPATIBILITY_LEVEL = 100 
GO 
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled')) 
begin 
EXEC [Test].[dbo].[sp_fulltext_database] @action = 'enable' 
end 
GO 
ALTER DATABASE [Test] SET ANSI_NULL_DEFAULT OFF 
GO 
ALTER DATABASE [Test] SET ANSI_NULLS OFF 
GO 
ALTER DATABASE [Test] SET ANSI_PADDING OFF 
GO 
ALTER DATABASE [Test] SET ANSI_WARNINGS OFF 
GO 
ALTER DATABASE [Test] SET ARITHABORT OFF 
GO 
ALTER DATABASE [Test] SET AUTO_CLOSE OFF 
GO 
ALTER DATABASE [Test] SET AUTO_CREATE_STATISTICS ON 
GO 
ALTER DATABASE [Test] SET AUTO_SHRINK OFF 
GO 
ALTER DATABASE [Test] SET AUTO_UPDATE_STATISTICS ON 
GO 
ALTER DATABASE [Test] SET CURSOR_CLOSE_ON_COMMIT OFF 
GO 
ALTER DATABASE [Test] SET CURSOR_DEFAULT GLOBAL 
GO 
ALTER DATABASE [Test] SET CONCAT_NULL_YIELDS_NULL OFF 
GO 
ALTER DATABASE [Test] SET NUMERIC_ROUNDABORT OFF 
GO 
ALTER DATABASE [Test] SET QUOTED_IDENTIFIER OFF 
GO 
ALTER DATABASE [Test] SET RECURSIVE_TRIGGERS OFF 
GO 
ALTER DATABASE [Test] SET DISABLE_BROKER 
GO 
ALTER DATABASE [Test] SET AUTO_UPDATE_STATISTICS_ASYNC OFF 
GO 
ALTER DATABASE [Test] SET DATE_CORRELATION_OPTIMIZATION OFF 
GO 
ALTER DATABASE [Test] SET TRUSTWORTHY OFF 
GO 
ALTER DATABASE [Test] SET ALLOW_SNAPSHOT_ISOLATION OFF 
GO 
ALTER DATABASE [Test] SET PARAMETERIZATION SIMPLE 
GO 
ALTER DATABASE [Test] SET READ_COMMITTED_SNAPSHOT OFF 
GO 
ALTER DATABASE [Test] SET HONOR_BROKER_PRIORITY OFF 
GO 
ALTER DATABASE [Test] SET READ_WRITE 
GO 
ALTER DATABASE [Test] SET RECOVERY SIMPLE 
GO 
ALTER DATABASE [Test] SET MULTI_USER 
GO 
ALTER DATABASE [Test] SET PAGE_VERIFY CHECKSUM 
GO 
ALTER DATABASE [Test] SET DB_CHAINING OFF 
GO 
USE [Test] 
GO 
/****** Object: Table [dbo].[Table2] Script Date: 08/07/2012 14:32:32 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Table2](
    [Company2ID] [int] NOT NULL, 
    [COmpanyAddress] [nchar](10) NULL, 
CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED 
(
    [Company2ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
/****** Object: Table [dbo].[Table1] Script Date: 08/07/2012 14:32:32 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Table1](
    [Company1ID] [int] NOT NULL, 
    [CompanyName] [nchar](10) NULL, 
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
    [Company1ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
/****** Object: Table [dbo].[Table3] Script Date: 08/07/2012 14:32:32 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Table3](
    [EMployeeID] [int] NOT NULL, 
    [Company] [int] NULL, 
CONSTRAINT [PK_Table3] PRIMARY KEY CLUSTERED 
(
    [EMployeeID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
/****** Object: ForeignKey [FK_Table3_Table1] Script Date: 08/07/2012 14:32:32 ******/ 
ALTER TABLE [dbo].[Table3] WITH CHECK ADD CONSTRAINT [FK_Table3_Table1] FOREIGN KEY([Company]) 
REFERENCES [dbo].[Table1] ([Company1ID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 
GO 
ALTER TABLE [dbo].[Table3] CHECK CONSTRAINT [FK_Table3_Table1] 
GO 
/****** Object: ForeignKey [FK_Table3_Table2] Script Date: 08/07/2012 14:32:32 ******/ 
ALTER TABLE [dbo].[Table3] WITH CHECK ADD CONSTRAINT [FK_Table3_Table2] FOREIGN KEY([Company]) 
REFERENCES [dbo].[Table2] ([Company2ID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 
GO 
ALTER TABLE [dbo].[Table3] CHECK CONSTRAINT [FK_Table3_Table2] 
GO 
+2

那麼,第一個問題將是爲什麼2公司表? – 2012-08-07 06:26:21

+0

我給了這個簡單的例子因爲我不能解釋你真實的情況。說一下,在一些遺留系統中有2個這樣的表,現在我無法改變它:) – GuruC 2012-08-07 06:30:15

+1

你說外鍵在SQL Server 2008中「工作」 - 但我敢打賭你實際上並沒有獲得外鍵約束在數據庫中聲明。 – 2012-08-07 06:33:26

回答

0

你的感覺是對的。 。 。這不是「正確的」。或者,至少,這是一個糟糕的設計決定。

但是,您的外鍵關係可能是一個複合鍵。一般來說,你會有另一列指定哪個表引用。複雜的是,這可能是一個「隱含的」列。所以,如果一個表有美國地址和其他非美國地址,那麼這兩個表都不會有「IsUS」標誌。但是,美國的記錄會提到一張桌子,而非美國的則是指向另一張桌子。

另一個問題是如何維護這些密鑰。你真的不想有兩個具有相互依賴的主鍵的表。解決這個問題的典型方法是將兩個表合併爲一個。

雖然這是一個糟糕的主意,但您可能不得不忍受這種結構。如果你可以改變它,你應該。

相關問題