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

C# 如何将DBNull值传递给参数化SELECT语句?,c#,sql-server,ado.net,C#,Sql Server,Ado.net,我在C#(针对SQL Server 2k8运行的.NET Framework 4)中有一条SQL语句,如下所示: SELECT [Column1] FROM [Table1] WHERE [Column2] = @Column2 上述查询可以与以下ADO.NET代码配合使用: DbParameter parm = Factory.CreateDbParameter(); parm.Value = "SomeValue"; parm.ParameterName = "@Column2"; //e

我在C#(针对SQL Server 2k8运行的.NET Framework 4)中有一条SQL语句,如下所示:

SELECT [Column1] FROM [Table1] WHERE [Column2] = @Column2
上述查询可以与以下ADO.NET代码配合使用:

DbParameter parm = Factory.CreateDbParameter();
parm.Value = "SomeValue";
parm.ParameterName = "@Column2";
//etc...
但是,如果我将DBNull.Value分配给DbParameter的Value成员,即使Column2中有null值,该查询也会返回零行。如果我更改查询以适应空测试:

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

我在运行时遇到了一个“靠近'@Column2'的语法错误”异常。我不能在SELECT语句的WHERE子句中使用null或DBNull作为参数吗?

将第二行更改为:

parm.Value = DbNull.Value;
这就是你要做的,真的。在本例中,不要担心
=
之间的关系


在我所处的位置,我们在项目之间共享的自制数据访问层也会自动检查所有查询参数,并在执行查询之前用
DbNull.Value
替换任何C#
null

将第二行更改为:

parm.Value = DbNull.Value;
这就是你要做的,真的。在本例中,不要担心
=
之间的关系

在我所处的位置,我们在项目之间共享的自制数据访问层也会自动检查所有查询参数,并在执行查询之前用
DbNull.Value
替换任何C#
null

您可以使用

SELECT [Column1] FROM [Table1] WHERE [Column2] = ISNULL(@Column2 , 'value');
“value”可以是您希望它表示的任何值。如果要匹配包含空列的column2

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

SELECT [Column1] FROM [Table1] WHERE [Column2] = ISNULL(@Column2 , 'value');
“value”可以是您希望它表示的任何值。如果要匹配包含空列的column2

SELECT [Column1] FROM [Table1] WHERE ISNULL([Column2], 'value') = ISNULL(@Column2 , 'value');
但我不确定这有多重要

编辑:这实际上看起来不错,至少在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

但我不确定这有多重要

编辑:这实际上看起来不错,至少在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
您可以使用:

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();
问候

您可以使用:

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();

问候

您确定它们的值为NULL而不仅仅是空字符串吗?如果是后者,它确实不会返回任何记录。正如Joel在他的回答中所说的,你应该在C代码中将
null
更改为
DbNull.Value
。如果是第一次,则应将其与
'
进行比较

如果数据确实为空,您可以尝试以下语句(如果您使用的是存储过程):


查看以下内容以获得更多信息。

您确定这些值是空的,而不仅仅是空字符串吗?如果是后者,它确实不会返回任何记录。正如Joel在他的回答中所说的,你应该在C代码中将
null
更改为
DbNull.Value
。如果是第一次,则应将其与
'
进行比较

如果数据确实为空,您可以尝试以下语句(如果您使用的是存储过程):



请查看以下内容以获得更多信息。

记住null不等于null。试着用LIKE代替ISOne note。将字符串字段设置为NOTNULL是值得的,不必担心此类问题。添加or或ISNull或COALESCE确实可以提高性能。@LukLed-请参阅我的答案
中的执行计划,这似乎不会导致出现问题
其中[Column2]=@Column2或(@Column2为NULL,[Column2]为NULL)
似乎是一种可识别的模式,并以简单的索引查找结束。@Martin:您检查了一个特定的案例,但并不总是相同的。也许它在这里工作得很好,但是使用函数是危险的,Dan应该意识到这一点。@LukLed-我同意这就是为什么我特意检查我的答案中的模式是否是可搜索的。记住null不等于null。试着用LIKE代替ISOne note。将字符串字段设置为NOTNULL是值得的,不必担心此类问题。添加or或ISNull或COALESCE确实可以提高性能。@LukLed-请参阅我的答案
中的执行计划,这似乎不会导致出现问题
其中[Column2]=@Column2或(@Column2为NULL,[Column2]为NULL)
似乎是一种可识别的模式,并以简单的索引查找结束。@Martin:您检查了一个特定的案例,但并不总是相同的。也许它在这里工作得很好,但使用函数是危险的,Dan应该意识到这一点。@LukLed-我同意这就是为什么我特意检查我的答案中的模式是否可搜索的原因。当我尝试这样做时,即使Column2中有空值,查询也总是返回零行。downvote,因为我尝试了这个方法(连接到MS SQL Server和SQLite)但它不起作用。得到了与Dan相同的结果。当我尝试这样做时,即使Column2中有空值,查询也将始终返回零行。Downvoted,因为我尝试了这样做(连接到MS SQL Server和SQLite)它不起作用。所有检查都得到了与Dan相同的结果。+1用于所有检查,但我仍然建议基于参数动态创建SQL。+1用于所有检查,但我仍然建议基于参数动态创建SQL。这当然有效,尽管我不喜欢我的查询为了容纳null而变得多么丑陋参数中的值。这当然有效,尽管我不喜欢我的查询为了适应参数中的空值而变得多么丑陋。