日期:2014-05-18  浏览次数:20981 次

为什么.net程序员不喜欢使用预处理sql语句
日题

实不相瞒,鄙人最近以前是搞JAVA的,最近又参加了一个.net项目。

发现代码使用的都是字符串拼接成的sql语句,要不就是存储过程

为什么不用预处理语句?象这样

SqlCommand sqlCmd = new SqlCommand(........) ;

sqlCmd. CommandText = ″insert into user( username, password) values (@ username, @ password) ″;

sqlCmd. Parameters. Add ("@ username", "aaaa") ;

sqlCmd. Parameters. Add ("@ password", "bbbbbbbb") ;

sqlCmd. Prepare( ) ;

sqlCmd. ExecuteNonQuery( ) ;

。。。。。。

预处理语句顾名思义就是预编译好的SQL程序,除了第一次需要解释编译外,性能与存储过程相当,为什么没人用??


------解决方案--------------------
为什么没人用??

如果你你看到的都没用,不是写程序的人不负责任,就是是存储过程传递参数,最终应该还是参数传递才行。仅仅拼接的SQL语句只能内部使用,和用户交互的场合不可使用,否则会有很大程度产生SQL注入,让你防不胜防。
------解决方案--------------------
如果不重复执行,prepare啥用也没有
------解决方案--------------------
LZ见过几个.net程序员写的.net程序?怎么就知道不喜欢用?
------解决方案--------------------
探讨
我表达可能不好,终于在网上博客找到一遍文章来说明这个问题,不一定表示博主就是正确,我所表述的意思跟这个一致,

另外,可能我写的那个真不是预处理sql,JAVA对预处理sql的支持很明确

仅供参考。。


以下内容转帖

原帖地址:http://hi.baidu.com/zagelover/blog/item/e130e1a17fefe08d46106451.html?echoback=baidu&_t=0.37414278247802485

1.

ALTER PROCEDURE [dbo].[test]
AS
DECLARE
@statment    NVARCHAR(300)      -- 构造sql语句
BEGIN
SET @statment = 'SELECT ' + '1*10+20+15' + ' AS RESULT';
-- 方式一   预处理语句应该会使用 EXEC sp_executesql模式,这里楼主加的,微软官方无此说明,仅供参考
    EXEC sp_executesql @statment
-- 方式二   普通sql语句
      EXEC (@statment)
END


1.方式一支持参数替换,方式二不支持。

2.sp_executesql扩展存储过程与t-sql的execute功能相似,但有一点不同,
通过sp_executesql执行的执行计划会被缓存起来,可重复使用。

测试:nz.perfectaction nzperfect@gmail.com

下面测试sp_executesql和exec的性能差别

Create DATABASE T_DBGOUSE T_DBGOCreate TABLE TB(ID INT IDENTITY(1,1) PRIMARY KEY,NAME VARCHAR(20))
GO
Insert INTO TB Select 'A'Insert INTO TB Select 'B'Insert INTO TB Select 'C'
Insert INTO TB Select 'D'Insert INTO TB Select 'E'Insert INTO TB Select 'F'
GO
--清除缓存中所有元素
DBCC FREEPROCCACHE
--查看T_DB数据库使用的缓存
Select SQL AS EXEC_SQL,OBJTYPE AS EXEC_TYPE,* FROM MASTER..SYSCACHEOBJECTS Where DBID=DB_ID('T_DB') AND SQL LIKE '%Select * FROM TB Where NAME%' AND SQL NOT LIKE '%SYSCACHEOBJECTS%'ORDER BY SQL
结果为空,
--测试使用EXEC,
执行下面sql语块
DECLARE @SQL VARCHAR(2000)DECLARE @NAME VARCHAR(20)DECLARE @I
INTSET @I=1WHILE @I <=6BEGIN   
IF @I=1 SET @NAME='A'
IF @I=2 SET @NAME='B'
IF @I=3 SET @NAME='C'   
IF @I=4 SET @NAME='D'
IF @I=5 SET @NAME='E'
IF @I=6 SET @NAME='F'   
SET @SQL = 'Select * FROM TB Where NAME = '''+@NAME+''''   
EXEC(@SQL)   
SET @I = @I + 1
END
--查看T_DB数据库使用的缓存
Select SQL AS EXEC_SQL,OBJTYPE AS EXEC_TYPE,* FROM MASTER..SYSCACHEOBJECTS Where DBID=DB_ID('T_DB') AND SQL LIKE '%Select * FROM TB Where NAME%' AND SQL NOT LIKE '%SYSCACHEOBJECTS%'ORDER BY SQL
结果有六条记录如图:
这说明sql server 对于exec执行的sql语句,即使where字段是同一个,但值不一样,每次都需要重新编译,而使用不同的缓存。

--测试使用SP_EXECUTESQL,
执行下面sql语块
DECLARE @SQL NVARCHAR(2000)DECLARE @NAME NVARCHAR(20)DECLARE @I INTSET @I=1WHILE @I <=6BEGIN   
IF @I=1 SET @NAME='A'
IF @I=2 SET @NAME='B'
IF @I=3 SET @NAME='C'   
IF @I=4 SET @NAME='D'
IF @I=5 SET @NAME='E'
IF @I=6 SET @NAME='F'   
SET @SQL = 'Select * FROM TB Where NAME = @NAME'   
EXEC SP_EXECUTESQL @SQL,N'@NAME NVARCHAR(20)',@NAME   
SET @I = @I + 1
END
--查看缓存
Select SQL AS EXEC_SQL,OBJTYPE AS EXEC_TYPE,* FROM MASTER..SYSC