如何更改以下查询,以便我能够参数化SparePartNames
?
它返回所有维修ID,而不是所有强制性备件都被更改,换句话说,至少有一部分缺失。
请注意,备件的数量将来可能会更改名称。没有使用动态SQL的存储过程是否可行?如果没有,这个SP怎么样?
编辑:请注意,我不需要知道如何将列表/数组作为参数传递,这在SO上被问到了无数的时间。我还有一个Split
表值函数。我只是想知道如何重写查询以便能够加入(或其他)强制部分列表,这样我就能找到至少有一部分缺失的所有记录。那么可以使用像'1264-3212,1254-2975'
这样的varchar参数而不是NOT EXISTS
列表吗?如果首先不清楚,请注意混淆。
SELECT d.idData
FROM tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel
WHERE (m.ModelName = 'MT27I')
AND (d.fiMaxServiceLevel >= 2)
AND (d.Manufacture_Date < '20120511')
AND (NOT EXISTS
(SELECT NULL
FROM tabDataDetail AS td
INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
WHERE (td.fiData = d.idData)
AND (sp.SparePartName = '1264-3212'))
OR (NOT EXISTS
(SELECT NULL
FROM tabDataDetail AS td
INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
WHERE (td.fiData = d.idData)
AND (sp.SparePartName = '1254-2975'))
)
)
很遗憾,我不知道如何在这里使用sp.SparePartName IN/NOT IN(@sparePartNames)
。
答案 0 :(得分:2)
一种方法是创建一个分割分隔字符串的函数:
CREATE FUNCTION [dbo].[Split]
(
@Delimiter char(1),
@StringToSplit varchar(512)
)
RETURNS table
AS
RETURN
(
WITH Pieces(pieceNumber, startIndex, delimiterIndex)
AS
(
SELECT 1, 1, CHARINDEX(@Delimiter, @StringToSplit)
UNION ALL
SELECT pieceNumber + 1, delimiterIndex + 1, CHARINDEX(@Delimiter, @StringToSplit, delimiterIndex + 1)
FROM Pieces
WHERE delimiterIndex > 0
)
SELECT
SUBSTRING(@StringToSplit, startIndex, CASE WHEN delimiterIndex > 0 THEN delimiterIndex - startIndex ELSE 512 END) AS Value
FROM Pieces
)
使用备件名称填充表变量:
DECLARE @SpareParts TABLE
(
SparePartName varchar(50) PRIMARY KEY CLUSTERED
);
INSERT INTO @SpareParts
SELECT Value FROM dbo.Split(',', '1264-3212,1254-2975');
然后加入表变量:
SELECT d.idData
FROM tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel
WHERE (m.ModelName = 'MT27I')
AND (d.fiMaxServiceLevel >= 2)
AND (d.Manufacture_Date < '20120511')
AND EXISTS (
SELECT 1
FROM tabDataDetail AS td
INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
LEFT JOIN @SpareParts AS s ON s.SparePartName = sp.SparePartName
WHERE td.fiData = d.idData
AND s.SparePartName IS NULL
)
答案 1 :(得分:1)
假设存在(或将来)强制备件的表或视图,则可以使用SparePartName上的tabDataDetail / tabSparePart对的左连接替换exists的列表;使用td.fiSparePart is null
报告不匹配。
; with mandatorySpareParts (SparePartName) as (
select '1264-3212'
union all
select '1254-2975'
)
SELECT d.idData
FROM tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel
WHERE (m.ModelName = 'MT27I')
AND (d.fiMaxServiceLevel >= 2)
AND (d.Manufacture_Date < '20120511')
AND exists
(
SELECT null
from mandatorySpareParts msp
left join ( tabDataDetail AS td
INNER JOIN tabSparePart AS sp
ON sp.idSparePart = td.fiSparePart
AND td.fiData = d.idData
)
ON msp.SparePartName = sp.SparePartName
WHERE td.fiSparePart is null
)
部件名称应替换为其ID,这将简化左连接并加快查询速度。
编辑:我错误地在where子句中过滤了td,这使左连接无效。它现在属于它所属的ON子句。答案 2 :(得分:0)
使用表变量并加入其中。