-1

我有一个具有以下情况的 SQL Server 2012 Express 数据库。我有一个Sales、一个Purchase和一个Movement表。两者SalesPurchase汇总在Movement表中。

但我想控制数据的来源。基本上:

MOVEMENT_ID     TABLE_ID     RECORD_ID     PROD     QTY
1               PURCHASE     1             PENCIL   10
2               PURCHASE     2             ERASER   5
3               SALES        1             PENCIL   1
4               PURCHASE     3             MARKER   10

不要担心规范化部分,我只是想弄清楚我是否可以在Record_ID链接到列中指定的表的记录的列上有一个外键Table_ID。所以...

  • on ,我想要表格MovementID=1的第一条记录Purchase
  • on ,我想要表格MovementID=3的第一条记录Sales

这是可能吗?如果是,如何?

4

3 回答 3

1

这是可能吗?

不是直接的,我会热情地推荐带有单独 FK 的单独字段(正如其他人已经建议的那样)。

但是,由于您使用的是 MS SQL Server,您可以像这样间接执行此操作:

  1. 创建一个持久的1 个 计算列SALE_ID,即:
    • 当 TABLE_ID = 'SALES' 时等于 RECORD_ID
    • 否则为 NULL。
  2. 创建一个持久计算列 PURCHASE_ID,即:
    • 当 TABLE_ID = 'PURCHASE' 时等于 RECORD_ID
    • 否则为 NULL。
  3. 创建从 SALE_ID 到 Sales 表的 FK 和从 PURCHASE_ID 到 Purchase 表的单独 FK。

例如:

ALTER TABLE Movement
    ADD SALE_ID AS IIF(TABLE_ID = 'SALES', RECORD_ID, NULL) PERSISTED
    REFERENCES Sales (SALE_ID);

ALTER TABLE Movement
    ADD PURCHASE_ID AS IIF(TABLE_ID = 'PURCHASE', RECORD_ID, NULL) PERSISTED
    REFERENCES Purchase (PURCHASE_ID);

[SQL 小提琴]


1 SQL Server 禁止在非持久化计算列上创建 FOREIGN KEY。

于 2013-05-30T17:19:22.010 回答
0

根据您这样做的确切目的,这样的非规范化表可能不会太糟糕(即,如果它只是用于查询/分析)。然而,它可能变得难以维护(例如,当这些表中的 ID 具有不同的数据类型时会发生什么等)。您可能会做的一些查询示例

;WITH SalesMovement AS
(
    SELECT * FROM Movement
    WHERE TableName = 'Sales'
)
SELECT PROD, SUM(QTY) FROM SalesMovement
GROUP BY PROD

 

;WITH PurchaseMovement AS
(
    SELECT * FROM Movement
    WHERE TableName = 'Purchase'
)
SELECT * FROM Purchase p
INNER JOIN PurchaseMovement pm ON pm.Record_Id = p.Id

 

;WITH PurchaseMovement AS
(
    SELECT * FROM Movement
    WHERE TableName = 'Purchase'
)
, SalesMovement AS
(
    SELECT * FROM Movement
    WHERE TableName = 'Sales'
)
SELECT * FROM Purchase p, 
INNER JOIN Sales s ON s.SaleDate = p.PurchaseDate
INNER JOIN PurchaseMovement pm ON pm.Record_Id = p.Id
INNER JOIN SalesMovement sm ON sm.Record_Id = s.Id

每当您想重新加入原始数据时,您都必须过滤、投射以及您拥有的东西,这可能会成为真正的皮塔饼

另一件要考虑的事情是类似的东西是否SUM(Qty) = SUM(ProductsSold) + SUM(ProductsSales)有意义,你必须小心这种对表中数据的“滥用”。

于 2013-05-30T15:34:17.840 回答
0

听起来运动实际上是购买或销售的概括。如果是这样,请考虑使用

这将避免在一列中混合不同类型的 FK 的问题。移动表中的 PK 将引用购买或销售表中的 PK,视情况而定。更少的列和更少的混乱。

于 2013-05-30T17:52:48.053 回答