Sql server SQL server中的多对多关系-在基表中未插入时在外部表中添加引用

Sql server SQL server中的多对多关系-在基表中未插入时在外部表中添加引用,sql-server,stored-procedures,foreign-key-relationship,Sql Server,Stored Procedures,Foreign Key Relationship,我有两个表User和Item。用户表将包含用户详细信息,项目表将包含项目的唯一条目 现在,我正在创建一个多对多关系,其中有一个名为List的单独表,它将两个表的主键作为外键引用。现在,每个用户将传递一个csv字符串,该字符串将包含他想要的所有项目。这些项目将被添加到项目表中,其Id和用户Id将被放置在列表表中 这些表是这样创建的 CREATE TABLE dbo.Item ( Item_Id int identity(1,1) not null, Item_Name varchar(30) no

我有两个表
User
Item
。用户表将包含用户详细信息,项目表将包含项目的唯一条目

现在,我正在创建一个多对多关系,其中有一个名为
List
的单独表,它将两个表的主键作为外键引用。现在,每个用户将传递一个csv字符串,该字符串将包含他想要的所有项目。这些项目将被添加到项目表中,其Id和用户Id将被放置在列表表中

这些表是这样创建的

CREATE TABLE dbo.Item
(
Item_Id int identity(1,1) not null,
Item_Name varchar(30) not null,
PRIMARY KEY (Item_Id)
);

CREATE TABLE dbo.List
(
Item_Id int not null,
Users_Id varchar(11) not null,
);
存储过程看起来像这样

ALTER procedure [dbo].[Entry] 
    @User_Id varchar(11)
    @Items VARCHAR(MAX)=NULL
as 
begin
    INSERT INTO dbo.Item
    OUTPUT INSERTED.Item_Id INTO @OutputTbl(Item_Id) 
       SELECT Item_Name
       FROM [dbo].[Split] ( @Items, ',')  -- call the split function 

    INSERT INTO dbo.List
       SELECT Item_Id, @User_Id 
       FROM @OutputTbl
end
GO
现在,当有重复的
名称时,我想跳过在
表中的插入,但是条目应该单独放在
列表
表中

例如,如果User1给出了列表“Soap,shappo”,并将其插入ids1、2,则引用将添加到列表表中。 现在,当User2创建列表“Brush,Soap”时,名称Soap不应该在Item表中重复,而应该在引用表中添加Soap的Id,如

    UserID    |   ItemID
  ---------------------------
    User1         1 
    User1         2 
    User2         3 
    User2         1
这对我来说似乎很难,因为我检索插入记录的Id并将它们放在列表表中。当名称已经存在时,如何将它们放置在列表表中

ALTER procedure [dbo].[Entry] 
    @User_Id varchar(11)
    @Items VARCHAR(MAX)=NULL
as 
begin
    DECLARE @Items TABLE (Name VARCHAR(150));

    -- call the split function 
    INSERT INTO @ItemNames
       SELECT Item_Name
       FROM [dbo].[Split] ( @Items, ',');

    -- insert all new items into items
    INSERT INTO dbo.Item
    SELECT Item_Name
       FROM @Items
    except 
    select item_name from dbo.Item;

    -- insert user/item into list
    INSERT INTO dbo.List
    SELECT distinct Item_Id, @User_Id 
    from @Items iu
    join dbo.Item i on iu.item_name=i.item_name;
end
GO

这样,您只需插入尚未在表中的名称,并且必须将整个项目列表合并并插入到映射表中

我相信您可能试图一次完成太多的工作。
PROC
似乎有以下3个问题:

  • 从@Items输入逗号分隔字符串中拆分项目名称列表
  • 使用一组唯一的“可见”项目名称维护
    dbo.Item
    表(即向表中添加新项目)
  • 使用
    User:ItemId
    映射维护
    dbo.List
    ,而不管项目是“新的”还是“现有的”
  • 我将据此消除这些担忧:

    CREATE PROCEDURE [dbo].[Entry] 
        @User_Id varchar(11),
        @Items VARCHAR(MAX)=NULL
    AS BEGIN
        DECLARE @ItemNames TABLE (Name NVARCHAR(50));
        DECLARE @ItemIds TABLE (Item_Id INT);
    
        INSERT INTO @ItemNames(Name)
            SELECT Item_Name FROM [dbo].[Split] ( @Items, ',');
    
        INSERT INTO dbo.Item(Item_Id)
            SELECT Name
            FROM @ItemNames new
            WHERE NOT EXISTS(SELECT 1 FROM dbo.Item i WHERE i.Item_Id = new.Name);
    
        INSERT INTO dbo.List(itm.Item_Id, User_Id)
           SELECT Item_Id, @User_Id 
           FROM @ItemNames new
            INNER JOIN dbo.Item itm
            ON itm.Item_Id = new.Name;
    END;
    

    我编辑代码,将名称实际存储为可诱惑的名称,而不是Id,然后我使用内部联接从可诱惑的名称中的相应名称在列表中插入Id。适用于我的存储过程是

    CREATE procedure [dbo].[Entry]
    @Users_Id varchar(11),
    @Items VARCHAR(MAX)=NULL
    as 
    begin
    DECLARE @ItemNames TABLE (Item_Names VARCHAR(150));
    
    INSERT INTO @ItemNames 
    SELECT Item_Name  
    FROM [dbo].[Split] ( @Items, ',')  -- call the split function 
    
    INSERT INTO dbo.Item
    SELECT Item_Names
    FROM @ItemNames list
    WHERE NOT EXISTS(SELECT 1 FROM dbo.Item i WHERE i.Item_Name = list.Item_Names);
    
    INSERT INTO dbo.List(Item_Id,Users_Id)
    SELECT  Item_Id,@Users_Id 
    FROM @ItemNames list
    INNER JOIN dbo.Item 
        ON list.Item_Names = dbo.Item.Item_Name;
    end
    GO
    

    我编辑了我的问题,问我真正想做什么??如果关键字的Id已存在于项目中,我如何将其插入列表中,因为我的过程将返回仅插入的关键字的Id,而仅插入的关键字的Id将插入列表表感谢它的帮助1+