Sco*_*ell 5 sql-server stored-procedures
我有一个带有WHERE子句的查询,该子句包含一个条件,该条件针对可能为NULL的参数检查NULLable列,如下所示:
SELECT ...
FROM Table
WHERE NullableColumn = @NullableParameter
Run Code Online (Sandbox Code Playgroud)
根据我的理解,SQL Server应该NULL = NULL non-NULL = NULL总是评估为false,这意味着如果@NullableParameter为NULL则上述查询将返回零记录.
这是我在查询窗口中运行查询时看到的行为,但是当我在存储过程中使用相同的查询时,当@NullableParameter为NULL时,它返回所有记录NullableColumn为NULL.简而言之,似乎sproc说的NULL = NULL是真的.
这就是问题/问题.实际WHERE条款涉及更多,并在下面的部分中提供更多细节.
我有一个名为StudyResults的数据库.每个记录由StudyResultId主键字段唯一标识.还有一个ParticipantId字段,表示研究中涉及的主题,并且GroupId标识该主题属于哪个组(如果有的话).如果该研究是单人研究,GroupId则为NULL.ParticipantId不能为NULL.
我有一个存储过程,需要更新StudyResults表中某些特定研究的记录,但这里有一点 - 如果研究是单人研究,那么我需要更新那一行; 如果是小组研究,我想更新该组的StudyResults中的所有行.
这不是很难完成.传递存储过程a StudyResultId然后运行以下T-SQL以确定该行的值GroupId和ParticipantId值:
DECLARE @GroupId INT, @ParticipantId INT
SELECT @GroupId = GroupId,
@ParticipantId = ParticipantId
FROM StudyResults
WHERE StudyResult = @StudyResultId
Run Code Online (Sandbox Code Playgroud)
接下来,我创建一个CURSOR来枚举感兴趣的StudyResults记录.请注意该WHERE子句,其中说:"给我的记录StudyResultId等于@StudyResultId传递到sproc中的值或者GroupId和ParticipantId值一起使用的是GroupId与感兴趣ParticipantId的StudyResults记录的值和值.
DECLARE resultsToEnumerate CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT StudyResultId
FROM StudyResults
WHERE StudyResult = @StudyResultId OR (GroupId = @GroupId AND ParticipantId= @ParticipantId)
Run Code Online (Sandbox Code Playgroud)
如果@GroupId为NULL,则比较GroupId = @GroupId应始终为false,对吧?因为对于SQL Server,它NULL = NULL是false,并且non-NULL = NULL是false.
但这就是它变得奇怪 - 如果我从查询窗口运行上述语句并使用@StudyResultId单人研究,CURSOR包含我所期望的 - 即单个记录.但是,如果我将完全相同的代码放在存储过程中并运行它,则CURSOR包含该参与者的所有单人研究!就好像它是说@GroupIdNULL,所以我将返回所有记录GroupId为NULL,但为什么呢?NULL = NULL永远不应该回复记录吧?
事实上,如果我进入sproc并更改WHERE条款并替换GroupID = @GroupID为NULL = NULLI ,我会看到相同的结果 - 所有参与者的单人研究.所以它显然是NULL = NULL在sproc中评估为true(或忽略它).
我可以通过在括号中添加一个额外的检查来"修复"存储过程,以确保GroupId IS NOT NULL如下:
WHERE ActivityID = @ActivityID OR (GroupID IS NOT NULL AND GroupID = @GroupID AND PatientID = @PatientID)
Run Code Online (Sandbox Code Playgroud)
这就是我所做的,但我很困惑为什么WHERE在我的存储过程中对子句的评估方式不同.
Jef*_*dge 12
将ANSI_NULLS设置为ON后,尝试更改会话中的存储过程.
SET ANSI_NULLS ON
GO
alter procedure procedureName
...
Run Code Online (Sandbox Code Playgroud)
来自文档:
对于存储过程,SQL Server使用存储过程的初始创建时间的SET ANSI_NULLS设置值.每当随后执行存储过程时,SET ANSI_NULLS的设置将恢复为其最初使用的值并生效.在存储过程中调用时,SET ANSI_NULLS的设置不会更改.
| 归档时间: |
|
| 查看次数: |
6088 次 |
| 最近记录: |