SQL中困扰我的概念

SQL语句的分类

编程方式分类

       SQL语句从编程的方式可以分为:交互式SQL和嵌入式SQL。交互式SQL不能适用于具有过程化特征的实际应用,也不能适用于查询结果数据进行处理的要求,也就是说,交互式SQL不适合大众对数据库的处理,因为大众是不懂SQL的,SQL就是针对数据库的操作,对于业务逻辑上没有自己的优势,所以,出现了嵌入式SQL。

       交互式SQL:在DBMS上直接对数据库进行的操作(字符命令)就是交互式SQL;嵌入式SQL:高级语言中写了SQL语句的就是嵌入式SQL,这个是广义上的理解。之前的嵌入式SQL编程只是在源代码级上对DBMS独立的,现在的嵌入式SQL编程(ODBC,ADO,ADO.net等)在源代码级和可执行代码级都独立于DBMS。可执行代码级独立于DBMS的思想和面向对象的思想有些类似,抽象各类数据库的功能,形成标准的接口,把标准接口呈现给应用程序开发者,程序只需到标准的接口这步就行,不需要再依靠特定的DBMS了。


编译和运行角度分类

        SQL语句从编译和运行的角度可以分为两种:静态SQL和动态SQL。

        静态SQL:SQL语句直接被编译,其运行时,直接运行就行;动态SQL:SQL语句以变量的形式被编译,其运行时,会产生所需SQL语句,然后编译这条SQL语句,编译出这条SQL语句后在运行。

        从上面的解释中,我们可以知道,交互式SQL和嵌入式SQL都可以有静态SQL和动态SQL,存储过程可以有静态SQL,也可以有动态SQL语句。SQL语句的字段值动态变化时,不影响其编译结果,如果是字段名、表名或数据库名改变时,那么就不能编译成确定的指令了,也就是说SQL语句字段值动态改变时,可以用静态SQL的形式,也可以用动态SQL的形式,但是,SQL语句的字段名、表名或数据库名改变时,必须使用动态SQL的形式。


动态SQL的基本语法

       1 :普通SQL语句可以用Exec执行 eg:

              Exec('select * from tableName')

              Exec sp_executesql N'select * from tableName' -- 请注意字符串前一定要加N

       2:字段名,表名,数据库名之类作为变量时,必须用动态sql语句eg:

             declare @fname varchar(20)

             set @fname = 'FiledName'

             Exec('select ' + @fname + ' from tableName') -- 请注意 加号前后的单引号的边上加空格 当然将字符串改成变量的形式也可

             declare @fname varchar(20)

             set @fname = 'FiledName' --设置字段名

             declare @s varchar(1000)

             set @s = 'select ' + @fname + 'from tableName'

             Exec(@s) -- 成功 exec sp_executesql @s --此句会报错

             declare @s Nvarchar(1000) -- 注意此处改为nvarchar(1000)

             set @s = 'select ' + @fname + ' from tableName' Exec(@s) -- 成功

             exec sp_executesql @s -- 此句正确

       3:输出参数

             declare @num int, @sqls nvarchar(4000)

             set @sqls='selectcount(*) from tableName'

             exec(@sqls)

             --如何将exec执行结果放入变量中?

             declare @num int, @sqls nvarchar(4000)

             set @sqls='select@a=count(*) from tableName '

             exec sp_executesql @sqls,N'@a int output',@numoutput select @num


动态SQL和静态SQL的总结

       动态SQL是使用exec 或exec sp_executesql的形式执行字符串变量或字符串常量,其中字符串变量、常量里面存放的是SQL语句,编译的只是字符串变量或字符串常量;静态的SQL是直接编译了;exec可以执行非Unicode或Unicode类型的字符串常量、变量,而exec sp_executesql只能执行Unicode或可以隐式转换为ntext的字符串常量、变量。


SQL注入

       静态SQL:交互式SQL,在DBMS中直接写的SQL语句执行时,如果其里面有变量,系统会将变量当成一个独立的部分,他不会影响其他的部分,例:declare @UserID varchar(20)  Set @UserID = '1'  Select * from DataTable where UserID = @UserID,无论我们在@UserID中赋予什么值,它仅在UserID这个字段上其作用,所以,交互式的SQL没有SQL注入的那一说;(基于标准接口)嵌入式SQL,我们给数据库引擎的是字符串SQL,我们知道在传送字符串SQL时,应用程序其实已经确定了SQL语句,如果我们在应用程序中直接拼接了完整的SQL,那么,我们就会出现那种SQL注入,例:dim strSQL as string = "Select * from DataTable Where UserID = '" + intUserID +"'",此时变量intUserID为1时,应用程序传送的SQL语句就是:Select * from DataTable Where UserID = '1',如果变量为1 or 1 = 1时,应用程序传送的SQL语句就是:Select * from DataTable Where UserID = '1' or 1 = 1,这两个的意思完全不一样,这个就是SQL注入。在宿主语言(写有SQL语句的高级语言)中,一般都设定某种防注入的机制,其原理是DBMS会将字段值变量部分当成独立部分,不影响其他部分。.net的SqlParameters的参数传递也是这个原理,字段值和SQL语句分开传送。

       动态SQL:嵌入式SQL的应用程序中一般不书写动态SQL,如果有需要,它一般会在DBMS中的存储过程书写;交互式动态SQL没有防注入的能力,因为其本质也是,字符串拼接SQL,所以,.net中的SqlParameters的参数传递机制也不能避免SQL注入,此时就需要在.net应用程序书写函数用于过滤某些关键字!


总结

      这篇博客的内容仅为自己的理解,耗时3天,用一段话描述这个过程:今天很残酷,明天更残酷,但后天太阳就出来了!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值