简体   繁体   English

如何将DBNull值传递给参数化的SELECT语句?

[英]How do I pass a DBNull value to a parameterized SELECT statement?

I have a SQL statement in C# (.NET Framework 4 running against SQL Server 2k8) that looks like this: 我在C#中有一条SQL语句(针对SQL Server 2k8运行的.NET Framework 4),如下所示:

SELECT [Column1] FROM [Table1] WHERE [Column2] = @Column2

The above query works fine with the following ADO.NET code: 上面的查询可以与以下ADO.NET代码一起正常工作:

DbParameter parm = Factory.CreateDbParameter();
parm.Value = "SomeValue";
parm.ParameterName = "@Column2";
//etc...

This query returns zero rows, though, if I assign DBNull.Value to the DbParameter's Value member even if there are null values in Column2. 即使我将DBNull.Value分配给DbParameter的Value成员,此查询也会返回零行,即使Column2中有空值。 If I change the query to accommodate the null test specifically: 如果我更改查询以专门容纳null测试:

SELECT [Column1] FROM [Table1] WHERE [Column2] IS @Column2

I get an "Incorrect syntax near '@Column2'" exception at runtime. 我在运行时收到“'@ Column2'附近的语法不正确”的异常。 Is there no way that I can use null or DBNull as a parameter in the WHERE clause of a SELECT statement? 我无法在SELECT语句的WHERE子句中使用null或DBNull作为参数吗?

SELECT [Column1] 
FROM [Table1] 
WHERE [Column2] = @Column2  OR (@Column2 IS NULL AND [Column2] IS NULL)

But I'm not sure how sargable this is. 但是我不确定这有多可靠。

Edit: This looks fine actually and ends up with an index seek at least in 2008 编辑:这看起来实际上很好,并最终至少在2008年寻求索引

CREATE TABLE [Table1]
(
[Column1] INT,
[Column2] INT 
)

CREATE CLUSTERED INDEX [IX] ON [dbo].[Table1] ([Column2] ASC)

INSERT INTO [Table1] VALUES(1,NULL)
INSERT INTO [Table1] VALUES(2,NULL)
INSERT INTO [Table1] VALUES(3,1)
INSERT INTO [Table1] VALUES(4,1)
GO

CREATE PROC foo
@Column2 INT
AS
SELECT [Column1] 
FROM [Table1] 
WHERE [Column2] = @Column2  OR (@Column2 IS NULL AND [Column2] IS NULL)

GO

EXEC foo NULL
EXEC foo 1

计划

you may use 你可以用

SELECT [Column1] FROM [Table1] WHERE [Column2] = ISNULL(@Column2 , 'value');

'value' can be any value that u want it to represent. “值”可以是您希望其表示的任何值。 If you want to match column2 that has null columns, 如果要匹配具有空列的column2,

SELECT [Column1] FROM [Table1] WHERE ISNULL([Column2], 'value') = ISNULL(@Column2 , 'value');

You can use: 您可以使用:

var cmd =new SqlCommand("SELECT ISNULL([Column1],'VALUE') as [Column1]  FROM [Table1] WHERE [Column2] = @Column2"),
                            con) 

string a;
if(textbox.text == string.empty)
{ a = DbNull.Value}
else { a =textbox.text}

cmd.Parameters.AddWithValue("@Column2",a);
cmd.ExecuteNonQuery();

regards! 问候!

Are you sure that they the values are NULL and not just empty strings? 您确定它们的值是NULL而不是空字符串吗? If it's the latter, it would indeed not return any record. 如果是后者,则确实不会返回任何记录。 And as Joel stated in his answer, yoou should allways change your null to DbNull.Value in your C#-code. 正如Joel在回答中所说的,您应该始终将您的null更改为C#代码中的DbNull.Value If it's the first you should compare to '' instead. 如果是第一个,则应将其与''进行比较。

If the data is indeed NULL, maybe you can try this statement (if you're using stored procedures): 如果数据确实为NULL,则可以尝试使用以下语句(如果使用存储过程):

SET ANSI_NULLS OFF

SELECT [Column1] FROM [Table1] WHERE [Column2] = NULL

Take a look at the folowing article for some extra insight. 请看以下文章,以获取更多的见解。

Change your second line to this: 将第二行更改为:

parm.Value = DbNull.Value;

That's all you have to do, really. 真的,这就是您要做的全部。 Don't worry about the = vs IS in this instance. 在这种情况下,不必担心= vs IS

Where I'm at, our homegrown data access tier that we share among projects also checks all query parameters automatically and replaces any C# null with DbNull.Value before executing the query. 我在哪里,我们在项目之间共享的本地数据访问层还自动检查所有查询参数,并在执行查询之前用DbNull.Value替换任何C# null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM