sqlserver 脚本和批处理指令小结

一.脚本基础
     1.use语句
          设置当前数据库。
     2.声明变量
          语法:declare @变量名 变量类型
          在声明变量后,给变量赋值之前,变量的值为null。
          将系统函数赋给声明的变量,这个方法可以使我们能更安全地使用值,该值只有人为地改变时它才变动。如果直接使用系统函数本身,那么当它发生变动时,有
     时会无法确定其究竟为何,因为大多数系统函数值是由系统确定的。这容易在你不预期的情况下导致系统改变了值,引起不可预期的后果。
          (1).给变量赋值
               set:当进行变量赋值是,该值已经知道是确切值或者是其他变量时,使用set。
               select:当变量赋值基于一个查询时,使用select。
          (2).系统函数
               sql server 2005中有30多个无参的系统函数,其中一些最重要的如下:
               @@error:                    返回当前连接下,最后执行的t-sql语句的错误代码,如无错误返回0。
               @@fetch_status:       和fetch语句配合使用。
               @@identity:                返回最后一句运行语句的、自动生成的标识值,作为最后insert或者select into语句的结果。
               @@rowcount:              返回最后一个语句影响的行数。
               @@servername:          返回脚本正在其上运行的本地服务的名字。
               @@trancount:            返回活动事务的数量,特别是针对当前连接的事务的瓶颈程度。

二.批处理
     (1).go单独占一行。在同一行上,t-sql语句不能在go语句之前。
     (2).所有语句从脚本开始处或者上一个go语句开始编译,直到下一个go语句或者脚本结束,将这段代码编译到一个执行计划中并相互独立地送往服务器。前一
 个执行计划中发生错误,不会影响后一个执行计划。
     (3).go不是一个t-sql命令,只是被编辑工具识别的命令。当编辑工具碰到go,它把go看做一个结束批处理的标记,将其打包,然后作为一个独立单元发送到
 服务器——不包括go,服务器对于go没有任何概念。         
     1.批处理中的错误
          语法错误,运行时错误。
     2.何时使用批处理
          (1).独自成批处理的语句
               有几个命令必须独自成批处理,它们包括:
                    create default
                    create procedure
                    create rule
                    create trigger
                    create view
               如果想将这些语句中的任何一条和其他语句组成单独的一个脚本,那么需要采用一个go语句将它们分别断开,归入各自的批处理中。
          (2).使用批处理建立优先级
               使用批处理最可靠的例子是,当需要考虑语句执行的优先顺序时,也就是说,需要一个任务在另一个任务开始前执行。
               例如:
                    create database test                    

复制代码 代码如下:

create table testtable

(

col1 int,

col2 int

)

               执行语句,会发现生成的表没有在test数据库中,而是在master数据库中(如果当前使用的数据库是系统数据库)。因为在执行脚本的时候,使用的数据

          库是系统数据库,该数据库是当前的,所以生成的表在系统数据库中。看起来,应该在创建表之前指定数据库test。然而,这样仍然存在问题。解析器试图校

          验代码,发现我们用use命令引用的数据库并不存在。原因在于创建数据库的语句和创建表的语句写在一个批处理中,在执行该脚本之前,当然数据库还没有

          创建。根据批处理的要求,我们将创建数据库和创建表的脚本用go语句分为两个独立的批处理。正确代码如下:


复制代码 代码如下:

create database test

go

use test

create table testtable

(

col1 int,

col2 int

)

三.动态sql:使用exe命令生成代码
     语法:exec/execute ({<字符串变量> | ‘<字面值命令字符串>’})

     1.exec的作用域

          真正的调用exec语句的行,拥有同该exec语句正在运行的批或过程中的其他代码相同的作用域。但是作为exec语句结果而被执行的代码,被认为是在它自

     己的批中。

          例如:

          declare @outvar varchar(50)

          exec (‘select @outvar = firstname from contact where contactid = 1’)

          这里系统会报错,指出必须声明变量@outvar。因为exec的语句独自成为一个批处理,其中的变量不能和其外的作用域相沟通,只在这个批处理中有效。此

     时,@outvar的值为null。正确的写法如下:

          exec (‘declare @outvar varchar(50)

                    select @outvar = firstname from contact where contactid = 1′)

          这里,我们看到两中不同的作用域,这两种作用域间不能相互沟通。如果不采用外部机制,比如一个临时表,我们就没有办法实现在内部作用域和外部作用域

     之间传递信息。有一个例外的事情是可以在exec的区域内部出现,并且也能在exec执行后被看到,这就是系统函数。因此,像@@rowcount这样的变量仍然

     能够被使用。

     2.安全上下文和exec

          当赋予某人权利运行一个存储过程,意味着他也能获得权利去执行存储过程内部的动作。比如,有一个存储过程用来列出去年内所有的雇佣员工。其中有权限

     执行该存储过程的人,才能够执行并返回结果——即使他没有权限直接访问人力资源的员工表。

          这样隐含权限对于exec语句是无效的。在默认情况下,任何在一个exec语句内部建立的参照,都将在当前用户的安全上下文中运行。因此,我们有权利去访

     问一个叫spnewemployee的存储过程,但是却没有权利去访问员工表。如果spnewemployee通过一个简单的select语句获得值,那么一切正常。但是如果

     pnewemployee使用exec语句去执行一个select语句,这个exec语句将失败——因为没有权利访问员工表。

     3.用户自定义函数和exec关联

          不能在同一个语句中同时运行一个函数和exec语句。例如:

          declare @num int

          set @num = 3

          exec (‘select left(lastname, ‘ + cast(@num as varchar) + ‘) as filingname from contact’)

          这个语句会返回一个错误消息,因为cast函数需要在exec所在行之前被解析。正确代码如下:

          declare @num int

          declare @str varchar(255)

          set @num = 3

          set @str = ‘select left(lastname, ‘ + cast(@num as varchar) + ‘) as filingname from contact’

          exec (@str)

          这个例子工作正常,因为exec的输入值已经是一个完整的字符串。

     4.exec和用户自定义函数

          一般来说,不允许用户自定义函数内部使用exec去运行动态sql,但是,使用exec运行一个存储过程,少数情况是合法的。

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐