Sql server 使用表值参数将值插入表中的存储过程
鉴于以下简单结构:Sql server 使用表值参数将值插入表中的存储过程,sql-server,sql-server-2008,Sql Server,Sql Server 2008,鉴于以下简单结构: TABLE: Product (ProductId, ProductName) TABLE: Category (CategoryId, CategoryName) LINK TABLE: ProductId,CategoryId 我有一个表类型,我想将它传递给存储过程,以便在不存在值的情况下将它们插入到另一个表中 CREATE TYPE StringList_TBLType AS TABLE (s NVARCHAR(255) NOT NULL PRIMARY KEY)
TABLE: Product (ProductId, ProductName)
TABLE: Category (CategoryId, CategoryName)
LINK TABLE: ProductId,CategoryId
我有一个表类型,我想将它传递给存储过程,以便在不存在值的情况下将它们插入到另一个表中
CREATE TYPE StringList_TBLType AS TABLE (s NVARCHAR(255) NOT NULL PRIMARY KEY)
我想在一个存储过程中执行以下操作,其中传入一个ProductName和类别名称的StringList\u TBLType
我可能会努力工作,但我对MS SQL和一般的存储过程几乎没有经验,我担心我最终会编写一种效率非常低的方法来完成这项工作。您可以使用
MERGE
语句来捕获类别ID
DECLARE @changes TABLE (ChangeID VARCHAR(10), Id INTEGER);
DECLARE @JustSomeRandomVariable INT;
MERGE Category AS TARGET
USING @data AS SOURCE
ON TARGET.Category = SOURCE.s
WHEN NOT MATCHED THEN
INSERT ([Category])
VALUES (SOURCE.s)
WHEN MATCHED THEN
UPDATE SET @JustSomeRandomVariable = 1
OUTPUT $action, inserted.Id INTO @changes;
merge语句中的随机变量确保更新被记录到@changes表变量中
现在您可以使用@changes更新链接表
INSERT INTO Link SELECT ProductID, ChangeID FROM @changes
只需通过简单的select查询检索所需的ProductID
编辑:
这可能会导致链接表中出现双记录。您可能需要对其进行一些调整,也可以使用MERGE语句插入到链接表中
@数据是您的过程的StringList\u TBLType参数。这是我的建议(未测试)
我会避免使用游标,除非没有其他方法。如果你真的需要游标,那么如果你想在T-SQL中解决它,你需要三思。一般来说,它们需要更多的代码(更难维护),而且性能更差。有趣的是。。。以前从未听说过merge,但经过一些阅读,@changes表似乎只有新类别的id?我还需要现有类别的ID,因为两者都需要进入链接表我为自己做了一个测试(SQL Server 2008 R2),通过添加分配的太
@JustSomeRandomVariable
进行更新,它还捕获@changes中的更新。啊,听起来我应该试一试,看看会发生什么!JodyT,我花了一段时间才让它工作起来,因为我的存储过程有141行长,而且我对它还不熟悉。这是令人沮丧的,但我学到了很多,并感谢您的帮助,这样一个优雅的解决方案!非常感谢。如果您使用相同的产品和一个或多个相同类别调用存储过程两次,那么它也会将它们插入链接
表两次。除非您自己检查链接中是否已经存在该关系。
CREATE PROCEDURE AddProductToCategories
@productname nvarchar(255),
@categories StringList_TBLType READONLY
AS
BEGIN
DECLARE @productId bigint --change to datatype of Product.ProductId
SET @productId = (SELECT TOP 1 ProductId FROM Product WHERE ProductName = @productname) --What to do if your product names are not unique?
IF @productId is not NULL
BEGIN
DECLARE cur CURSOR FOR (
SELECT cat.CategoryName, cat.CategoryId, c.s
FROM @categories c
RIGHT OUTER JOIN Category cat on c.s = cat.CategoryName
)
DECLARE @id as bigint --change to datatype of Category.CategoryId
DECLARE @name as nvarchar(255) --change to datatype of Category.CategoryName
DECLARE @categoryNameToAdd as nvarchar(255)
OPEN cur
FETCH NEXT FROM cur INTO @name, @id, @categoryNameToAdd
WHILE @@FETCH_STATUS = 0
BEGIN
IF @id is NULL
BEGIN
--category does not exist yet in table Category
INSERT INTO Category (CategoryName) VALUES (@categoryNameToAdd)
SET @id = SCOPE_IDENTITY()
END
INSERT INTO ProductsCategories --your link table
(ProductId, CategoryId)
VALUES
(@productId, @id)
FETCH NEXT FROM cur INTO @name, @id, @categoryNameToAdd
END --cursor
CLOSE cur
DEALLOCATE cur
END --IF @productId
END --sproc