Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 表内引用父项_Sql_Sql Server - Fatal编程技术网

Sql 表内引用父项

Sql 表内引用父项,sql,sql-server,Sql,Sql Server,我有一个具有以下结构的SQL Server表: create table Products ( Id int identity not null constraint primary key clustered (Id), Name nvarchar (200) not null, ) 我需要允许一个产品引用另一个产品 目的是在列出产品时,展示一些产品的一种替代品 我可以将名为ProductId的FK添加到Products表中,但我有几个问题: 循环引用是否会

我有一个具有以下结构的SQL Server表:

create table Products
(
    Id int identity not null 
        constraint primary key clustered (Id),
    Name nvarchar (200) not null,
)
我需要允许一个
产品
引用另一个
产品

目的是在列出产品时,展示一些产品的一种替代品

我可以将名为
ProductId
的FK添加到
Products
表中,但我有几个问题:

  • 循环引用是否会产生问题
  • 如何防止
    Id
    ProductId
    相同?我不希望产品引用自身
    您可以在同一个表中放置替代项,如下所示:

    create table Products ( 
       ProductId int identity(1, 1) primary key,
       Name nvarchar(200) not null,
       Alternate_ProductId int references Products(ProductId),
       check (Alternate_ProductId <> ProductId)
    );
    
    创建表格产品(
    ProductId int标识(1,1)主键,
    名称nvarchar(200)不为空,
    替代产品ID int参考产品(产品ID),
    检查(备用产品ID ProductId ProductId)
    );
    
    请注意,在SQL Server中,主键是自动群集的,因此没有理由显式。此外,根据定义,主键不为NULL,因此
    notnull
    是冗余的

    Check约束允许
    NULL
    值通过(与
    WHERE
    CASE WHEN
    不同),因此您不必担心
    Alternate\u ProductId
    NULL


    这会引起问题吗?嗯,这只允许一种替代产品,这可能不够。此外,这使得未来可能会变得麻烦的替代产品链成为可能。

    我认为一个重要的问题是,您要具体模拟什么:

    • 对于任何给定产品,可以有1个(或更多)替代/等效产品(“同样好”)
    • 对于任何给定的产品类别,都有一个首选产品
    对于第一个选项,@Gordon的答案当然足够了(只要每个产品只需要1个备用)。如果一个产品可以有多个备选产品,您需要一个“备选产品”映射表(如@pmbAustin所建议的),或者(假设您有产品类别)只显示同一类别中的其他产品

    对于选项2(同样,假设您有产品类别或类似产品),您可以存储类别的首选产品:

    CREATE TABLE ProductCategories ( category_id INT IDENTITY(1,1) PRIMARY KEY, category_name NVARCHAR(255) NOT NULL, preferred_product INT NOT NULL FOREIGN KEY REFERENCES Products(Id) ); That way, if the user is looking at a "non-preferred" product, they can be shown the preferred product for that category (if it's defined). 创建表ProductCategories ( 类别id INT标识(1,1)主键, 类别名称NVARCHAR(255)不为空, 首选产品INT非空外键引用产品(Id) ); 这样,如果用户正在查看“非首选”产品,则可以向他们显示该类别的首选产品(如果已定义)。
    FK引用本身对SQL Server没有问题。您必须决定您的概念设计是否支持这一点。您可以编写一个触发器来验证FK是否未引用自身,然后在发生这种情况时回滚编辑/插入操作。是否确定始终显示一个备选方案?这通常会扩展到显示2、3、5等备选方案。您可以考虑使用一个单独的表来链接产品和推荐的替代品来实现。this@Martin是的,因为在这种情况下,替代品是一种替代品,我相信只有一种产品替代品会获得批准。事实上,我甚至不能有两个。是的,我几乎建议使用“AlternateProduct”映射表的替代设计,将产品映射到替代产品。这将允许一对多映射,并消除自引用问题,这有时可能是一个难题。我可以有一个备用表,但事实上一个产品只有一个备用表,因此拥有第二个表可能会增加开销?是的,我承认只有一个表在删除时可能会有一些问题,等等?我试图为每个产品建模一个可选的替代方案。而且只能是一个,因为只有一个会被批准。@Miguel:那么听起来好像@Gordon的答案更好。请注意,您可能会遇到循环问题(其中
    产品A
    产品B
    的替代品,反之亦然)。