如何在 Sql Server Compact Edition 中将参数与 LIKE 一起使用

Posted

技术标签:

【中文标题】如何在 Sql Server Compact Edition 中将参数与 LIKE 一起使用【英文标题】:How to use parameter with LIKE in Sql Server Compact Edition 【发布时间】:2009-12-16 17:27:04 【问题描述】:

我正在尝试参数化使用带有通配符的 LIKE 关键字的搜索查询。原来的sql有这样的动态sql:

"AND JOB_POSTCODE LIKE '" + isPostCode + "%' "

所以我尝试了这个,但我得到了一个 FormatException:

"AND JOB_POSTCODE LIKE @postcode + '%' "

编辑:我猜 FormatException 不会来自 Sql Server CE,所以按照要求,这是我在 C# 代码中设置参数的方式。参数在代码中设置如下:

command.Parameters.Add("@postcode", SqlDbType.NVarChar).Value = isPostCode;

我也试过了:

"AND JOB_POSTCODE LIKE @postcode"

command.Parameters.Add("@postcode", SqlDbType.NVarChar).Value = isPostCode + "%";

但这不会返回任何结果。谁能建议如何在此搜索 sql 中使用参数?

【问题讨论】:

完整查询:@"SELECT * FROM JOB WHERE DELETED = false AND JOB_POSTCODE LIKE '" + isPostCode + '%' " 【参考方案1】:

简短的回答是您应该将通配符放在参数的值中,而不是在命令文本中。即

不是这样的: sqlCommand.CommandText = "SELECT * FROM JOB WHERE JOB_POSTCODE LIKE @postcode%"

这个:

sqlCommand.CommandText = "SELECT * FROM JOB WHERE JOB_POSTCODE LIKE @postcode";
sqlCommand.Parameters.Add("@postcode", SqlDbType.NVarChar).Value = postCode + "%";

这里是长答案:

我回去并将我的代码剥离到基本要素,以便我可以将其发布在这里,同时我发现我在原始问题中尝试的最后一种方法确实有效。我的测试一定有问题。所以这里有一个摘要,其中包含已运行的完整代码:

原创动态sql,易被sql注入:

//Dynamic sql works, returns 2 results as expected, 
//but I want to use parameters to protect against sql injection

string postCode = "G20";
sqlCommand.CommandText = "SELECT * FROM JOB WHERE JOB_POSTCODE LIKE '" 
                         + postCode + "%'";
return Database.fGetDataSet(sqlCommand, 
                            iiStartRecord, 
                            iiMaxRecords, 
                            "JOBVISIT");

第一次尝试使用参数时出错:

//This syntax with a parameter gives me an error 
//(note that I've added the NVarChar length as suggested:
//System.FormatException : @postcode : G20 - 
//Input string was not in a correct format.
//at System.Data.SqlServerCe.SqlCeCommand.FillParameterDataBindings()
//at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommandText(IntPtr& pCursor,
// Boolean& isBaseTableCursor)

string postCode = "G20";
sqlCommand.CommandText = "SELECT * FROM JOB WHERE JOB_POSTCODE LIKE @postcode 
                         + '%'";
sqlCommand.Parameters.Add("@postcode", 
                          SqlDbType.NVarChar, 
                          10).Value = postCode;
return Database.fGetDataSet(sqlCommand, iiStartRecord, iiMaxRecords, "JOBVISIT");

第二种方法确实有效:

///This syntax with a parameter works, returns 2 results as expected
string postCode = "G20";
sqlCommand.CommandText = "SELECT * FROM JOB WHERE JOB_POSTCODE LIKE @postcode";
sqlCommand.Parameters.Add("@postcode", SqlDbType.NVarChar).Value = postCode 
                                                                   + "%";
return Database.fGetDataSet(sqlCommand, iiStartRecord, iiMaxRecords, "JOBVISIT");

感谢您的所有意见,并对最初的误导性问题表示抱歉...

【讨论】:

SQLCE(或者,更有可能是提供者)的内联表达式一定有问题——这可能是提供者抛出错误的原因。我没有 SQLCE 测试平台,甚至没有注意到这确实是一个 SQL CE 问题,直到我已经发布了我的第一个答案:-( 凯德,感谢您的意见。它帮助我坚持我的代码和测试,并帮助我转向代码而不是 sql。【参考方案2】:

这会在 SQL Server 05 中返回适当的结果(也适用于包装在 SP 中),因此您尝试的最后一件事似乎应该有效。但是我没有紧凑版的测试平台,所以也许这会有所不同(我很想知道是不是这样,以及为什么)。

declare @p1 nvarchar(50)
set @p1 = 'f'         -- initial value passed from your app
set @p1 = @p1 + '%'   -- edit value for use with LIKE
select * from JOB
where JOB_POSTCODE like @p1

编辑:

您使用的是什么版本的 SQLCE?你能判断你的参数值是否真的从你的代码传递到数据库吗?我浏览了this MSDN tutorial 并能够获得您正在寻找的结果,至少来自 Visual Studio 查询设计器。 (唯一的区别是我使用的是 VS 2008 和 SQL Server Compact 3.5)。请参阅标题为“创建新查询”的部分;我用一些数据模拟了一个表,这个查询按你的意愿工作。

SELECT     JobID, PostCode, OtherValue
FROM         Job
WHERE     (PostCode LIKE @p1 + '%')

就像我说的,我没有编写任何代码来调用查询,但它在设计器内部工作。换句话说,“它可以在我的机器上运行”。

【讨论】:

Sql Server CE不允许命名参数,并且declare关键字不存在,所以我不能使用你的sql。我不知道如何在 Management Studio 中分配未命名的参数。我正在尝试这个: SELECT * FROM JOB WHERE JOB_POSTCODE LIKE ? + '%', 'G20' 但语法不正确 @Colin,我想我从你的评论中学到的比你从我的回答中学到的更多;)-也许编辑有帮助? Matt,感谢您的链接,现在我可以在我的代码之外测试参数化查询(我一直在尝试在 Management Studio 而不是 Server Explorer 中进行测试)。我不认为错误来自 SqlServerCE,我认为它来自 .NET Compact Framework 数据提供程序 - 请参阅我为错误文本发布的答案。作为记录,我使用的是 VS2005 和 Sql Server Compact 3.5【参考方案3】:

使用:

"AND JOB_POSTCODE LIKE '" + isPostCode + "%' "

...表示字符串是在附加到动态 SQL 之前构建的。这样您就不必在 sp_executesql/EXEC 的参数列表中指定参数,而这样:

"AND JOB_POSTCODE LIKE @postcode + '%' "

...确实。请发布更多查询。

【讨论】:

动态 sql 可以工作,但我想使用一个参数来防止 sql 注入,但我无法让它工作【参考方案4】:

请发布您的完整示例(包括您组装呼叫的外部客户端代码)。如果您正确传递参数,您的第二个和第三个选项都应该起作用。您是在存储过程还是内联参数化 SQL 中调用它?

我假设没有 SP,因为我刚刚看到您正在使用 CE...

我认为您需要add a length to your .Add call,因为它是nvarchar

【讨论】:

你是对的,没有 SP。它是内联参数化的 sql。我已编辑问题以添加将参数添加到命令的行。 SqlDbType.NVarChar 可能是问题吗? Cade,我尝试添加长度并发现它没有任何区别,但在更多测试期间我发现第三个选项有效。我很抱歉。有关所有详细信息,请参阅我发布的答案。我很好奇为什么第二个选项不起作用............【参考方案5】:
select province_address 
from address 
where (@postcode is null or postcode like '%' + @postcode '%')

如果你这样使用,这意味着如果你没有在@postcode 中发送任何值,它将带来所有,否则它只会带来包含@postcode

【讨论】:

【参考方案6】:

你的答案是:

"AND JOB_POSTCODE LIKE '' + @postcode + '%' "

和参数:

command.Parameters.Add("@postcode", SqlDbType.NVarChar).Value = isPostCode;

【讨论】:

以上是关于如何在 Sql Server Compact Edition 中将参数与 LIKE 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Sql Server Compact Edition SELECT 语句中复制 Rank 函数?

如何部署 SQL Server Compact Edition 4.0?

如何在 SQL Server Compact Edition 中重命名表?

如何在没有 Linq to SQL 的情况下在 Windows Phone 中使用 SQL Server Compact

在 SQL Server Compact 中返回标识

如何将 SQL Server Compact 3.5 与实体框架一起使用