我正在构建一个食谱网站,我正在尝试创建一个带有表值参数的存储过程,但遇到了一些问题。
因此,TVP 是根据用户在尝试搜索食谱时选择的复选框列表来填充的。然后我想根据这些选择显示食谱,因此我在存储过程中使用了 TVP。
但是,当用户未在复选框列表之一中选择任何选项时,我希望查询显示所有记录(对于每个部分)。当我尝试执行此操作时,查询立即不返回任何结果。
TVP 设置和逻辑
类别 | 难度 | 持续时间 |
---|---|---|
肉 | 简单 | 0-15 分钟 |
string.Empty | 平均 | 30-45 分钟 |
鱼 | 硬 | string.Empty |
我希望程序通过在类别、难度和持续时间中选择的所有选项过滤每个食谱。 IE。在这种情况下,我希望存储过程返回所有具有 Category = "Meat" 或 "Fish" 的食谱;难度 =“简单”或“平均”或“难”,持续时间 =“0-15 分钟”或“30-45 分钟”。
例如,如果 Category 中不存在任何值,则存储过程应返回所有类别的配方,并且仅根据具有值的列进行过滤。
目前的工作代码
ALTER PROCEDURE uspPesquisarReceita (@TVP dbo.Filters READONLY)
AS
BEGIN
SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration, R.Rating, R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1
AND (C.Category IN (SELECT Category FROM @TVP)
AND DF.Dificulty IN (SELECT Dificulty FROM @TVP)
AND D.Duration IN (SELECT Duration FROM @TVP))
END
此代码有效,仅当我在所有三个复选框列表(称为类别、难度和持续时间)中选择选项时。
我尝试过的代码 #1
ALTER PROCEDURE uspPesquisarReceita (@TVP dbo.Filters READONLY)
AS
BEGIN
SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration, R.Rating, R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1
AND (C.Category IN (CASE WHEN NOT EXISTS (SELECT Category FROM @TVP)
THEN
(SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration,
R.Rating, R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1)
ELSE (SELECT Category FROM @TVP)
AND DF.Dificulty IN (SELECT Dificulty FROM @TVP)
*same as above*
AND D.Duration IN (SELECT Duration FROM @TVP))
*same as above*
END
我尝试过的代码#2(仅以类别为例)
ALTER PROCEDURE uspPesquisarReceita (@TVP dbo.Filters READONLY)
AS
BEGIN
IF NOT EXISTS (SELECT Category FROM @TVP)
SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration, R.Rating,
R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1
AND DF.Dificulty IN (SELECT Dificulty FROM @TVP)
AND D.Duration IN (SELECT Duration FROM @TVP))
ELSE
SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration, R.Rating,
R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1
AND (C.Category IN (SELECT Category FROM @TVP)
AND DF.Dificulty IN (SELECT Dificulty FROM @TVP)
AND D.Duration IN (SELECT Duration FROM @TVP))
END
这两次尝试都没有产生任何结果。你能帮我吗?我错过了什么?
谢谢!
答案 0 :(得分:0)
我将建议类似以下内容 - 尽管正如 Dale 所指出的那样,当 @TVP 值填充不同的过滤器组合时,查看它的确切外观会很方便。但是,在此期间,请尝试一下,看看会得到什么结果。
ALTER PROCEDURE uspPesquisarReceita (@TVP dbo.Filters READONLY)
AS
BEGIN
SELECT R.RecipeName, C.Category, DF.Dificulty, D.Duration, R.Rating, R.Publication, R.Photo, R.Views, R.IDRecipe
FROM dbo.Recipes R
LEFT JOIN dbo.Categories C ON R.IDCategory = C.IDCategory
LEFT JOIN dbo.Dificulty DF ON R.IDDificulty = DF.IDDificulty
LEFT JOIN dbo.Duration D ON R.IDDuration = D.IDDuration
WHERE R.IDStatus = 1
AND
(
(C.Category IN (SELECT Category FROM @TVP))
OR
(NOT EXISTS (SELECT 1 FROM @TVP WHERE LTRIM(ISNULL(Category, '')) <> ''))
)
AND
(
(DF.Dificulty IN (SELECT Dificulty FROM @TVP))
OR
(NOT EXISTS (SELECT 1 FROM @TVP WHERE LTRIM(ISNULL(Dificulty, '')) <> ''))
)
AND
(
(D.Duration IN (SELECT Duration FROM @TVP))
OR
(NOT EXISTS (SELECT 1 FROM @TVP WHERE LTRIM(ISNULL(Duration, '')) <> ''))
)
END
基本上,我假设如果用户没有勾选特定过滤器的任何选项(类别、难度或持续时间),那么@TVP 表中将不会有相应列中有值的行。 (如果此假设不正确,那么我们将回到 Dale 的建议,即查看有关如何填充 @TVP 变量的更多详细信息 - 即您的应用程序端代码)