Отношение "много ко многим" в SQL server-добавить ссылку во внешнюю таблицу, когда вставка не происходит в базовую таблицу
У меня есть две таблицы User
и Item
. Пользовательская таблица будет содержать сведения о пользователе, а таблица элементов будет содержать уникальные записи элемента.
List
, которая ссылается на первичные ключи обеих таблиц как на внешний ключ. Теперь каждый пользователь будет передавать строку csv, которая будет содержать все элементы, которые он хочет. Эти элементы будут добавлены в таблицу элементов и его идентификатор вместе с идентификатором пользователя будет помещен в список стол.
Таблицы создаются следующим образом....
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
, но только запись должна быть помещена в таблицу List
.
Например, если пользователь 1 дал список "мыло, шампунь" и он вставлен с идентификаторами 1 , 2, и рефренсы будут добавлены в таблицу списка. Теперь, когда User2 делает список "щетка, мыло" имя Soap не следует дублировать в таблице Item, но идентификатор soap должен быть добавлен в справочную таблицу, например
UserID | ItemID
---------------------------
User1 1
User1 2
User2 3
User2 1
Это кажется трудным для меня, потому что я получаю идентификатор вставленных записей и помещаю их в таблицу списка. Как разместить их в таблице списка, когда имя уже присутствует.
3 ответа:
Я думаю, что вы, возможно, пытаетесь сделать слишком много сразу. У
PROC
, по-видимому, есть следующие 3 проблемы:
- разбиение списка имен элементов из строки ввода @Items через запятую
- сохранение таблицы
dbo.Item
с уникальным набором всех "видимых" имен элементов (т. е. добавление новых элементов в таблицу)- сохранение
dbo.List
с отображениямиUser : ItemId
независимо от того, является ли элемент "новым" или "существующим".Я бы разделил заботы соответственно:
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;
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
Таким образом, вы вставляете только имена, которых еще нет в таблице, и должны присоединиться ко всему списку элементов и вставить в таблицу сопоставления
Я отредактировал свой код, чтобы на самом деле хранить имена как temptable вместо ID, а затем я использовал внутреннее соединение, чтобы вставить Id в список из соответствующих имен в temptable.Хранимая процедура, которая работает для меня...
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