我正在开发一个C#项目,它从MS SQL Server 2008或2008 R2 Server读取值。
查询看起来像这样:
string charge="1234567";
string command = string.Format("SELECT * FROM tableX WHERE chargeField = '{0}' ", charge);
chargeField来自类型nvarchar(50) - 不要问我为什么 - 我无法更改数据库。 此外,条目由另一个工具写入数据库,我也无法更改。 有时,chargeField值会在其中包含前导或结尾空格字符,所以我的 查询将不返回任何内容,因为“1234567”!=“1234567”
但是,当我像这样编写查询时(没有''):
string command = string.Format("SELECT * FROM tableX WHERE chargeField = {0} ", charge);
它有效。为什么这甚至可以工作 - 我不需要''标志来表明数据库字段是一个字符串?我可以安全地更改所有查询吗?这是MS SQL Server的“功能”,以及这里发生了什么。
修改
我通过使用:
解决了这个问题string command = string.Format("SELECT * FROM tableX WHERE RTRIM(LTRIM(chargeField)) = {0} ", charge);
感谢。
答案 0 :(得分:1)
SQL Server会尝试相应地转换字段。如果没有引号,则传入一个数字,因此SQL Server会尝试将chargeField
中的值转换为数字,该数字尽管有前导空格。
如果chargeField
包含值12345a
,则无效。这将导致转换错误。表中的一条记录包含这样的值就足以得到错误。
为安全起见,请将查询更改为
... WHERE LTRIM(chargeField) = '{0}'
但要注意,这会导致不再使用该字段的可能索引。你仍然可以做的是创建一个额外的列,使用值为LTRIM(chargeField)
的触发器填充,在该列上放置索引并相应地调整WHERE
子句。
答案 1 :(得分:1)
当运算符组合了两种不同数据类型的表达式时,数据类型优先级的规则指定优先级较低的数据类型转换为优先级较高的数据类型
Numeric / int优先级高于nvarchar,因此查询等效于:
SELECT * FROM tableX WHERE CAST(chargeField as INT) = {0}
请注意,此类查询无法使用chargeField
上的索引。