不同表的SQL Server外键
我有一个SQL Server 2012 Express数据库,存在以下情况。 我有一张不同表的SQL Server外键,sql,sql-server,database-design,shared-primary-key,Sql,Sql Server,Database Design,Shared Primary Key,我有一个SQL Server 2012 Express数据库,存在以下情况。 我有一张销售、一张购买、一张移动表。 销售和采购都汇总在移动表中 但我想控制数据的来源。 基本上: MOVEMENT_ID TABLE_ID RECORD_ID PROD QTY 1 PURCHASE 1 PENCIL 10 2 PURCHASE 2 ERASER
销售
、一张购买
、一张移动
表。
销售
和采购
都汇总在移动
表中
但我想控制数据的来源。
基本上:
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\u ID
列上有一个外键,该列链接到table\u ID
列中指定的表的记录。
所以
- 在
上,我想要MovementID=1
表的第一条记录Purchase
- 在
上,我想要MovementID=3
表的第一条记录Sales
这有可能吗?如果是,怎么做?取决于您这样做的具体目的,那么像这样的非规范化表可能不会太糟糕(即,如果它只是用于查询/分析)。然而,它可能变得难以维护(例如,当这些表中的ID具有不同的数据类型时会发生什么情况等)。不过,您可以使用一些查询示例
;WITH SalesMovement AS
(
SELECT * FROM Movement
WHERE TableName = 'Sales'
)
SELECT PROD, SUM(QTY) FROM SalesMovement
GROUP BY PROD
无论何时,当您想要连接回原始数据时,您都必须进行过滤、强制转换,以及您拥有的可能会进一步成为真正的pita的内容
另一个要考虑的是,像<代码>和(QTY)=和(产品销售)+和(产品销售)< /> >是否有意义,你必须小心表中数据的这种“误用”。
这有可能吗 不是直接的,我强烈推荐使用单独的FK的单独字段(正如其他人已经建议的那样) 但是,由于您使用的是MS SQL Server,因此可以这样间接执行:- 当表_ID='SALES'时等于记录_ID'
- 否则无效
- 当表_ID='PURCHASE'时,等于记录_ID
- 否则无效
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);
1 SQL Server禁止在非持久化计算列上创建外键。听起来移动实际上是购买或销售的概括。如果是,请考虑使用.
这将避免在一个色谱柱中混合不同类型FK的问题。移动表中的主键将根据具体情况引用购买表或销售表中的主键。更少的列,也更少的混乱。“不要担心标准化部分”就像说不要担心你车上的爆胎,它会开得很好。我认为你最好使用三列
购买Id、销售Id、源表
如果你标准化,这个问题会以某种方式消失。搜索“超级类型/子类型”,有3种方法来解决这类问题。“CoTunp基金会”对于一个好的概念很重要。如果你坚持使用这样的方法,你就不能建立真正的引用完整性。不能使用ID+Type一次引用Sales
表,另一次引用Purchase
表。这是做不到的。不要这样做——这是一个可怕的设计理念。。。。。在移动中使用单独的ID列进行销售和购买-其中一个不是每行为空(另一个将为空)谢谢walter,这就是我要找的!我可以在这里做研究!!谢谢布兰科,我给了你一个+1的帮助。我想试试沃尔特的,因为它接近我的原始想法。如果它变得明显难以维护,那么我将为每个fk单独设置一列。
;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
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);