SQL 服务器中的多对多关系 - 在基础 table 中未发生插入时在外部 table 中添加引用
Many to many relationship in SQL server - To add reference in foreign table when insertion does not happen in base table
我有两个 tables User
和 Item
。用户 table 将拥有用户详细信息,项目 table 将拥有该项目的唯一条目。
现在我正在创建多对多关系,其中有一个名为 List
的单独 table,它引用两个 table 的主键作为外键。现在每个用户将传递一个 csv 字符串,其中包含他想要的所有项目。这些项目将添加到项目 table 中,其 ID 和用户 ID 将放在列表 table.
中
table 是这样创建的....
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
现在,当 Item
名称重复时,我想跳过 Item
table 中的插入,但单独的条目应该放在 List
table。
例如,如果 User1 给出了列表 "Soap,Shampoo" 并且它插入了 ID 1 和 2,并且引用将添加到列表 table 中。
现在,当 User2 列出 "Brush,Soap" 时,名称 Soap 不应在项目 table 中重复,但肥皂的 ID 应添加到引用 table 中,如
UserID | ItemID
---------------------------
User1 1
User1 2
User2 3
User2 1
这对我来说似乎很难,因为我检索了插入记录的 ID 并将它们放在列表 table 中。如何在名称已存在时将它们放入列表 table。
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
这样你只插入不在 table 中的名称并且必须加入整个项目列表并插入映射 table
我相信您可能一次尝试做太多事情。 PROC
似乎有以下 3 个问题:
- 从@Items 输入的逗号分隔字符串中分离出项目名称列表
- 使用一组唯一的所有 'seen' 项目名称维护
dbo.Item
table(即将新项目添加到 table)
- 使用
User : ItemId
映射维护 dbo.List
,无论项目是 'new' 还是 'existing'。
我会相应地分解问题:
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;
我编辑了我的代码以实际将名称存储为 temptable 而不是 ID,然后我使用 Inner join 从适合我的 temptable.The 存储过程中的相应名称将 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
我有两个 tables User
和 Item
。用户 table 将拥有用户详细信息,项目 table 将拥有该项目的唯一条目。
现在我正在创建多对多关系,其中有一个名为 List
的单独 table,它引用两个 table 的主键作为外键。现在每个用户将传递一个 csv 字符串,其中包含他想要的所有项目。这些项目将添加到项目 table 中,其 ID 和用户 ID 将放在列表 table.
table 是这样创建的....
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
现在,当 Item
名称重复时,我想跳过 Item
table 中的插入,但单独的条目应该放在 List
table。
例如,如果 User1 给出了列表 "Soap,Shampoo" 并且它插入了 ID 1 和 2,并且引用将添加到列表 table 中。 现在,当 User2 列出 "Brush,Soap" 时,名称 Soap 不应在项目 table 中重复,但肥皂的 ID 应添加到引用 table 中,如
UserID | ItemID
---------------------------
User1 1
User1 2
User2 3
User2 1
这对我来说似乎很难,因为我检索了插入记录的 ID 并将它们放在列表 table 中。如何在名称已存在时将它们放入列表 table。
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
这样你只插入不在 table 中的名称并且必须加入整个项目列表并插入映射 table
我相信您可能一次尝试做太多事情。 PROC
似乎有以下 3 个问题:
- 从@Items 输入的逗号分隔字符串中分离出项目名称列表
- 使用一组唯一的所有 'seen' 项目名称维护
dbo.Item
table(即将新项目添加到 table) - 使用
User : ItemId
映射维护dbo.List
,无论项目是 'new' 还是 'existing'。
我会相应地分解问题:
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;
我编辑了我的代码以实际将名称存储为 temptable 而不是 ID,然后我使用 Inner join 从适合我的 temptable.The 存储过程中的相应名称将 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