ado.net 参数传递之 in

时间:2023-03-10 02:26:19
ado.net 参数传递之 in

之前项目有一放行的功能,对某界面维护时(数据的增删改),先将数据保存到临时表中,放行后再真正的写入到库中。由于设计到主从表多中约束关系,所以当时我采用的是写一个存储过程来对某个界面的操作进行统一处理,具体参见关于MVC项目中的主管放行。现在sa 说不得使用存储过程为由让更改(开发文档中写明: 尽量少用存储过程),自以为仅仅是将sql 挪一个位置,实际在修改中 在 in 这个地方还是费了不少时间。

在谈及 in 之前,先说下参数传递的三种方式

1. 字符串拼接 ' "+str+" ' ,很容易理解,好用,所谓的字符串拼接,对于非前台界面传入的参数可以直接这样写,可避免sql 注入,前台输入的参数若直接用此方法,则可被sql注入

2. Parameter ,也常见,常规的操作直接传入参数即可 如update:  set A.name = @name   此处name经过sql 编译后 自动会加入单引号 ' '

3. 占位符 {0},用String.Format 拼接,当某段sql中存在出现多次相同的参数时,用此方法比较方便,如果用2,则要写para1,para2 ,para3,若用3,只需要写一个 ‘{0}’

上面的搞清楚了,现在来看一看 in 这个比较特殊的问题,当传递的参数本身就包含逗号时,就比较搅了,如 'a1,b1','a2,b2','a3,b3'

诸如: 用到IN的存储过程,需要转两个弯弯,先用EXEC( '   ' ) 包裹一遍,然后里面所用到的值都要加一个单引号,如 '' D'' , 对于IN后带@的参数,为 '+@str+',普通的参数加两对单引号

'''+@appuserid+'''
            EXEC('
--刪除
DELETE FROM A
WHERE TableKey IN
(SELECT TableKey FROM tempA WHERE sFlag = ''D'' AND ApplyUserID = '''+@appuserid+''' AND TableKey IN('+@str+')) --清空臨時資源表
DELETE FROM tempZT_SysConfig_Master WHERE TableKey IN ('+@str+');
')

诸如:一般不需要用到存储过程、事务和IN关键字的SQl 而言,直接写入即可(成功)

SELECT * FROM A  WHERE ApplyUserID = @ApplyUserID

诸如:带 IN 关键字的SQl,单个参数中不含逗号,如:  'A,B,C',或者参数含逗号,如 'a1,b1','a2,b2','a3,b3',采用如下方式去执行Sql,则为失败;若采用Trim('\'') 去掉首尾单引号,仍然失败。(采用 ExecuteScalar 去获取值,不报错,单结果为 0,正常应该为2)

 SELECT COUNT(*) FROM A  WHERE ApplyUserID IN(@ApplyUserID)

尝试了许久,最终改用占位符 { 0 } 解决,注: 普通占位符加单引号,IN 后面则不需要

 SELECT COUNT(*) FROM A  WHERE ApplyUserID IN({0}) AND NAME = '{1}'

其实占位符还有一个好处,由于之前写的储存过程中涉及的参数 @ApplyUserID 和 @Name 用到了多次,若使用字符串拼接觉得比较丑(小小的强迫症),若采用@Parameter 则需要定义很多变量,因为SQL中 Parameter 变量不能重复,而且碰到 IN 这种弯弯,绕起来又比较麻烦,故用占位符 {0} ,实际上操作起来很方便,对于sql中出现多次 @ApplyUserID 用 {0} 代替,@Name用 {1} 代替即可。占位符无关次数。