下面是一个存储过程,用于根据单独检查所有字段来检查数据库中是否存在重复条目(不要问我为什么要这样做,只需要这样)。
听起来非常简单,但SP失败了。 问题是传递给SP的一些参数可能具有空值,因此sql应该读为“is null”而不是“= null”。 我已尝试使用exec()和sp_executesql的isnull(),case语句,coalesce()和动态sql,但未能实现其中任何一个。这是代码......
CREATE PROCEDURE sp_myDuplicateCheck
@userId int,
@noteType char(1),
@aCode char(3),
@bCode char(3),
@cCode char(3),
@outDuplicateFound int OUT
AS
BEGIN
SET @outDuplicateFound = (SELECT Top 1 id FROM codeTable
WHERE userId = @userId
AND noteType = @noteType
AND aCode = @aCode
AND bCode = @bCode
AND cCode = @cCode
)
-- Now set the duplicate output flag to a 1 or a 0
IF (@outDuplicateFound IS NULL) OR (@outDuplicateFound = '') OR (@outDuplicateFound = 0)
SET @outDuplicateFound = 0
ELSE
SET @outDuplicateFound = 1
END
答案 0 :(得分:10)
对于每个可能为null的参数,我认为你需要这样的东西:
AND (aCode = @aCode OR (aCode IS NULL AND @aCode IS NULL))
答案 1 :(得分:7)
如果我理解你的问题,那么我鼓励你做一些研究:
SET ANSI_NULLS OFF
如果在存储过程中使用此命令,则可以在比较中使用= NULL。请查看以下示例代码,了解其工作原理。
Declare @Temp Table(Data Int)
Insert Into @Temp Values(1)
Insert Into @Temp Values(NULL)
-- No rows from the following query
select * From @Temp Where Data = NULL
SET ANSI_NULLS OFF
-- This returns the rows where data is null
select * From @Temp Where Data = NULL
SET ANSI_NULLS ON
每当您将ANSI_NULLS设置为Off时,最好尽快将其设置为ON,因为这可能会影响您稍后运行的其他查询。所有SET命令仅影响当前会话,但根据您的应用程序,这可能会跨越多个查询,这就是为什么我建议您在此查询后立即重新启用ansi null。
答案 2 :(得分:1)
我认为这应该适用于COALESCE功能。试试这个:
CREATE PROCEDURE sp_myDuplicateCheck
@userId int,
@noteType char(1),
@aCode char(3),
@bCode char(3),
@cCode char(3),
@outDuplicateFound int OUT
AS
BEGIN
SET @outDuplicateFound = (SELECT Top 1 id FROM codeTable
WHERE userId = @userId
AND noteType = @noteType
AND COALESCE(aCode,'NUL') = COALESCE(@aCode,'NUL')
AND COALESCE(bCode,'NUL') = COALESCE(@bCode,'NUL')
AND COALESCE(cCode,'NUL') = COALESCE(@cCode,'NUL')
)
-- Now set the duplicate output flag to a 1 or a 0
IF (@outDuplicateFound IS NULL) OR (@outDuplicateFound = '') OR (@outDuplicateFound = 0)
SET @outDuplicateFound = 0
ELSE
SET @outDuplicateFound = 1
END
祝你好运!
杰森
答案 3 :(得分:0)
我首先添加一个检查以查看所有参数在运行时是否为空,即
IF(COALESCE(@userId, @noteType, @aCode, @bCode, @cCode) IS NULL)
BEGIN
-- do something here, log, print, return, etc.
END
然后,在您验证用户传入的内容后,您可以在WHERE子句中使用类似的内容
WHERE userId = COALESCE(@userId, userId)
AND noteType = COALESCE(@noteType, noteType)
AND aCode = COALESCE(@aCode, aCode)
AND bCode = COALESCE(@bCode, bCode)
AND cCode = COALESCE(@cCode, cCode)
编辑:我可能错过了如果参数作为null传入的意图,这意味着您明确要将列测试为null。我上面的where子句假设null参数意味着'跳过此列上的测试。'
或者,我相信您可以使用原始查询并在存储过程创建时添加ANSI_NULLS set选项。例如,
SET ANSI_NULLS OFF
GO
CREATE PROC sp_myDuplicateCheck....
实际上,这应该允许您的代码然后评估column = null而不是column为null。我认为Kalen Delaney曾经将ANSI _NULLS和QUOTED_IDENTIFIER 选项创造为“粘性选项”,因为如果它们设置在过程创建时间,那么它们会在运行时保留该过程,无论其连接方式如何时间已经确定。
答案 4 :(得分:0)
试试这个:
CREATE PROCEDURE sp_myDuplicateCheck
@userId int = 0,
@noteType char(1) = "",
@aCode char(3) = "",
@bCode char(3) = "",
@cCode char(3) = "",
@outDuplicateFound int OUT
AS
BEGIN
SET @outDuplicateFound = (SELECT Top 1 id FROM codeTable
WHERE @userId in (userId ,0)
AND @noteType in (noteType,"")
AND @aCode in (aCode , "")
AND @bCode in (bCode , "")
AND @cCode in (cCode ,"")
)
-- Now set the duplicate output flag to a 1 or a 0
IF (@outDuplicateFound IS NULL) OR (@outDuplicateFound = '') OR (@outDuplicateFound = 0)
SET @outDuplicateFound = 0
ELSE
SET @outDuplicateFound = 1
END
这基本上做的是在null为空的情况下为输入参数提供默认值,然后在where条件中仅在 时为值提供默认值。
答案 5 :(得分:0)
SET ANSI_NULLS OFF/On
这样你就可以colName = null