将数据从 table 值参数插入 table
Inserting data into table from table-valued parameter
我正在尝试创建一个存储过程,向其传递一个 TVP,然后将来自 TVP 的一些数据插入到两个表中。
我已经实现了存储过程,但只有第二个插入(唯一一个不从 TVP 读取的插入)在工作。其他两个不工作(不要插入任何东西),我似乎无法弄清楚为什么。
我曾尝试在 SQL 服务器和 运行 那里的程序中创建一个虚拟 TVP,但这也没有用。这是因为 TVP 是只读的吗?我假设不会,因为我实际上并没有在 TVP 中插入或更新数据。
有没有办法让它工作?
感谢您的协助!
Table-值参数定义:
CREATE TYPE dbo.Ingredients
AS TABLE
(
Quantity int,
Measure nvarchar(50),
Ingredient nvarchar(50),
)
GO
存储过程:
ALTER PROCEDURE uspCreateRecipe
(@IDUser int,
@RecipeName nvarchar(50),
@Category nvarchar(50),
@Difficulty nvarchar(50),
@Duration nvarchar(50),
@ING dbo.Ingredients READONLY,
@Execution text)
AS
BEGIN
INSERT INTO dbo.Ingredients
VALUES ((SELECT Ingredient FROM @ING WHERE NOT EXISTS (SELECT Ingredient FROM @ING WHERE Ingredient IN (SELECT IngredientName FROM dbo.Ingredients))), 2)
INSERT INTO dbo.Recipes
VALUES (@IDUser, @RecipeName, NULL,
(SELECT IDDifficulty FROM dbo.Difficulty WHERE Difficulty = @Difficulty),
(SELECT IDDuration FROM dbo.Duration WHERE Duration = @Duration ),
NULL,
(SELECT IDCategory FROM dbo.Category WHERE CategoryName = @Category ),
@Execution , NULL, 2, GETDATE())
INSERT INTO dbo.Recipes_Ingredients
VALUES (SCOPE_IDENTITY(),
(SELECT Quantity FROM @ING),
(SELECT IDMeasure FROM dbo.Measure WHERE Measure IN (SELECT Measure FROM @ING)),
(SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName IN (SELECT Ingredient FROM @ING)))
END
- 不要将
VALUES
用于子查询,只需使用 SELECT
.
- 始终列出要插入的列。它更清晰并且会减少错误,特别是如果您将来修改 table 结构,
- 您的第一个查询似乎过于复杂 - 如果它确实有效的话。
- 您的第三个查询应该会引发错误,因为您有多个
IN
子查询应该会导致“子查询返回多个结果”错误。
text
数据类型已弃用 varchar(max)
。
- 通常你想要
SET NOCOUNT, XACT_ABORT ON
。
- 始终
RETURN
一个状态,以便您的调用应用知道它是否成功。 0 将默认返回,我更愿意明确。
- 分号终止所有语句。
ALTER PROCEDURE uspCreateRecipe
(
@IDUser int
, @RecipeName nvarchar(50)
, @Category nvarchar(50)
, @Difficulty nvarchar(50)
, @Duration nvarchar(50)
, @ING dbo.Ingredients READONLY
, @Execution nvarchar(max) -- text is depreciated
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
INSERT INTO dbo.Ingredients ([Name], Col2)
SELECT Ingredient, 2
FROM @ING
WHERE Ingredient NOT IN (SELECT IngredientName FROM dbo.Ingredients);
INSERT INTO dbo.Recipes (IDUser, RecipeName, Col3, IDDifficulty, IDDuration, Col6, IDCategory, Col8, Col9, Col10, Co11)
SELECT @IDUser, @RecipeName, NULL, IDDifficulty
, (SELECT IDDuration FROM dbo.Duration WHERE Duration = @Duration)
, NULL
, (SELECT IDCategory FROM dbo.Category WHERE CategoryName = @Category)
, @Execution, NULL, 2, GETDATE()
FROM dbo.Difficulty
WHERE Difficulty = @Difficulty;
INSERT INTO dbo.Recipes_Ingredients (IDRecipe, Quantity, IDMeasureid, IDIngredient)
SELECT SCOPE_IDENTITY(), Quantity
, (SELECT IDMeasure FROM dbo.Measure WHERE Measure = I.Measure)
, (SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName = I.Ingredient)
FROM @ING I;
RETURN 0;
END;
我正在尝试创建一个存储过程,向其传递一个 TVP,然后将来自 TVP 的一些数据插入到两个表中。
我已经实现了存储过程,但只有第二个插入(唯一一个不从 TVP 读取的插入)在工作。其他两个不工作(不要插入任何东西),我似乎无法弄清楚为什么。
我曾尝试在 SQL 服务器和 运行 那里的程序中创建一个虚拟 TVP,但这也没有用。这是因为 TVP 是只读的吗?我假设不会,因为我实际上并没有在 TVP 中插入或更新数据。
有没有办法让它工作?
感谢您的协助!
Table-值参数定义:
CREATE TYPE dbo.Ingredients
AS TABLE
(
Quantity int,
Measure nvarchar(50),
Ingredient nvarchar(50),
)
GO
存储过程:
ALTER PROCEDURE uspCreateRecipe
(@IDUser int,
@RecipeName nvarchar(50),
@Category nvarchar(50),
@Difficulty nvarchar(50),
@Duration nvarchar(50),
@ING dbo.Ingredients READONLY,
@Execution text)
AS
BEGIN
INSERT INTO dbo.Ingredients
VALUES ((SELECT Ingredient FROM @ING WHERE NOT EXISTS (SELECT Ingredient FROM @ING WHERE Ingredient IN (SELECT IngredientName FROM dbo.Ingredients))), 2)
INSERT INTO dbo.Recipes
VALUES (@IDUser, @RecipeName, NULL,
(SELECT IDDifficulty FROM dbo.Difficulty WHERE Difficulty = @Difficulty),
(SELECT IDDuration FROM dbo.Duration WHERE Duration = @Duration ),
NULL,
(SELECT IDCategory FROM dbo.Category WHERE CategoryName = @Category ),
@Execution , NULL, 2, GETDATE())
INSERT INTO dbo.Recipes_Ingredients
VALUES (SCOPE_IDENTITY(),
(SELECT Quantity FROM @ING),
(SELECT IDMeasure FROM dbo.Measure WHERE Measure IN (SELECT Measure FROM @ING)),
(SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName IN (SELECT Ingredient FROM @ING)))
END
- 不要将
VALUES
用于子查询,只需使用SELECT
. - 始终列出要插入的列。它更清晰并且会减少错误,特别是如果您将来修改 table 结构,
- 您的第一个查询似乎过于复杂 - 如果它确实有效的话。
- 您的第三个查询应该会引发错误,因为您有多个
IN
子查询应该会导致“子查询返回多个结果”错误。 text
数据类型已弃用varchar(max)
。- 通常你想要
SET NOCOUNT, XACT_ABORT ON
。 - 始终
RETURN
一个状态,以便您的调用应用知道它是否成功。 0 将默认返回,我更愿意明确。 - 分号终止所有语句。
ALTER PROCEDURE uspCreateRecipe
(
@IDUser int
, @RecipeName nvarchar(50)
, @Category nvarchar(50)
, @Difficulty nvarchar(50)
, @Duration nvarchar(50)
, @ING dbo.Ingredients READONLY
, @Execution nvarchar(max) -- text is depreciated
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
INSERT INTO dbo.Ingredients ([Name], Col2)
SELECT Ingredient, 2
FROM @ING
WHERE Ingredient NOT IN (SELECT IngredientName FROM dbo.Ingredients);
INSERT INTO dbo.Recipes (IDUser, RecipeName, Col3, IDDifficulty, IDDuration, Col6, IDCategory, Col8, Col9, Col10, Co11)
SELECT @IDUser, @RecipeName, NULL, IDDifficulty
, (SELECT IDDuration FROM dbo.Duration WHERE Duration = @Duration)
, NULL
, (SELECT IDCategory FROM dbo.Category WHERE CategoryName = @Category)
, @Execution, NULL, 2, GETDATE()
FROM dbo.Difficulty
WHERE Difficulty = @Difficulty;
INSERT INTO dbo.Recipes_Ingredients (IDRecipe, Quantity, IDMeasureid, IDIngredient)
SELECT SCOPE_IDENTITY(), Quantity
, (SELECT IDMeasure FROM dbo.Measure WHERE Measure = I.Measure)
, (SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName = I.Ingredient)
FROM @ING I;
RETURN 0;
END;