不同表的SQL Server外键

不同表的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

我有一个SQL Server 2012 Express数据库,存在以下情况。 我有一张
销售
、一张
购买
、一张
移动
表。
销售
采购
都汇总在
移动
表中

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

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,因此可以这样间接执行:

  • 创建一个persisted1计算列SALE\u ID,即:
    • 当表_ID='SALES'时等于记录_ID'
    • 否则无效
  • 创建一个持久化的计算列ID,该ID为:
    • 当表_ID='PURCHASE'时,等于记录_ID
    • 否则无效
  • 创建从销售标识到销售表的FK和从采购标识到采购表的单独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);
    



    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);