SQLSREVER如何创建和使用动态游标

▲创建游标

CREATE PROCEDURE Usp_CreateCursor(@Select_Command varchar(8000),@Cursor_Return CURSOR VARYING OUTPUT) AS
/*存储过程名称:Usp_CreateCursor
功能描述: 根据指定的SELECT创建一个动态游标
参数描述: @Select_Command ---SELECT语句;@Cursor_Return ---要返回的游标变量
思路: 动态游标的关键是不知如何去构造它的SELECT语句,因为SELECT是个字符串表量,定义时不能直接用它,但它可以来源于表。
所以我的目的就是创建一个统一的表,从中取数据不就可以了。建表有一定的语法规则,所以就应该根据栏位列表生成相应的
格式,这个可以从系统表中获取。关键的问题是如何将数据插入到临时表,我摸索出一条语句可
实现这个功能,那就是INSERT INTO

  1<table_name> EXECUTE <sql>,而SQL7.0的帮助未讲。有表有数据就可以创建了。   
  2创建人: 康剑民   
  3创建日期: 2001-07-11   
  4*/   
  5Declare @Select_Command_Temp Varchar(8000), ---存放SELECT临时语法   
  6@Table_List varchar(255), ---存放表的列表   
  7@Column_List varchar(8000),---存放栏位列表   
  8@Table_Name varchar(30),---存放单独表名   
  9@Column_Name varchar(30),---存放单独栏位名(但有可能是*)   
 10@Column_Syntax varchar(8000),---存放栏位建表时的语法(综合)   
 11@Column_Name_Temp varchar(30),---存放栏位名称   
 12@Column_Type_Temp varchar(30),----存放栏位类型   
 13@Column_Syntax_Temp varchar(8000),---存放栏位建表时的语法(单个)   
 14@Column_Length_Temp int,---存放栏位长度   
 15@Column_Xprec_Temp int,---存放栏位精度   
 16@Column_Xscale_Temp int,---存放栏位小数位数   
 17@From_Pos int,---存放from的位置   
 18@Where_Pos int,---存放where的位置   
 19@Having_Pos int,---存放having的位置   
 20@Groupby_Pos int,---存放groupby的位置   
 21@Orderby_Pos int,---存放orderby的位置   
 22@Temp_Pos int,---临时变量   
 23@Column_Count int,---存放栏位总数   
 24@Loop_Seq int---循环步进变量 
 25
 26\---创建临时表   
 27Create Table #Test(a int)   
 28\---如果传来的SELECT语句不是以'select'开头,自动修改   
 29If Left(Lower(Ltrim(@Select_Command)),6) &lt;&gt; 'select' Select @Select_Command = 'Select ' + @Select_Command   
 30\---将开头‘SELECT’去掉   
 31Select @Select_Command_Temp = Lower(Ltrim(@Select_Command))   
 32If Left(@Select_Command_Temp,6) = 'select' Select @Select_Command_Temp = Right(@Select_Command_Temp,Len(@Select_Command_Temp) - 7)   
 33\---取各保留字位置,以便获得表的列表   
 34Select @From_Pos = CHARINDEX(' from ',@Select_Command_Temp)   
 35Select @Where_Pos = CHARINDEX(' where ',@Select_Command_Temp)   
 36Select @Having_Pos = CHARINDEX(' having ',@Select_Command_Temp)   
 37Select @Groupby_Pos = CHARINDEX(' groupby ',@Select_Command_Temp)   
 38Select @Orderby_Pos = CHARINDEX(' orderby ',@Select_Command_Temp) 
 39
 40If @Where_Pos &gt; 0 Select @Temp_Pos = @Where_Pos   
 41If @Having_Pos &gt; 0 And @Having_Pos &lt; @Temp_Pos Select @Temp_Pos = @Having_Pos   
 42If @Groupby_Pos &gt; 0 And @Groupby_Pos &lt; @Temp_Pos Select @Temp_Pos = @Groupby_Pos   
 43If @Orderby_Pos &gt; 0 And @Orderby_Pos &lt; @Temp_Pos Select @Temp_Pos = @Orderby_Pos   
 44\---取表列表   
 45If @Temp_Pos &gt; 0   
 46Begin   
 47Select @Table_List = SUBSTRING(@Select_Command_Temp,@From_Pos + 6 ,@Temp_Pos - @From_Pos - 1)   
 48End   
 49Else   
 50Begin   
 51Select @Table_List = SUBSTRING(@Select_Command_Temp,@From_Pos + 6 ,Len(@Select_Command_Temp) - @From_Pos - 1)   
 52End 
 53
 54Select @Column_Syntax = ''   
 55\---只列出栏位   
 56Select @Select_Command_Temp = Left(@Select_Command_Temp,@From_Pos - 1)   
 57While Len(@Select_Command_Temp) &gt; 0   
 58Begin   
 59\---取逗号位置   
 60Select @Temp_Pos = CHARINDEX(',',@Select_Command_Temp)   
 61\---初次取栏位名称   
 62If @Temp_Pos &gt; 0   
 63Begin   
 64Select @Column_Name = Left(@Select_Command_Temp,@Temp_Pos - 1)   
 65End   
 66Else   
 67Begin   
 68Select @Column_Name = @Select_Command_Temp   
 69End   
 70\---取表名和栏位名(可能是‘*’)   
 71If CHARINDEX('.',@Column_Name) &gt; 0   
 72Begin   
 73Select @Table_Name = Left(@Column_Name,CHARINDEX('.',@Column_Name) - 1)   
 74Select @Column_Name = Right(@Column_Name,Len(@Column_Name) - CHARINDEX('.',@Column_Name))   
 75End   
 76Else   
 77Begin   
 78Select @Table_Name = @Table_List   
 79End 
 80
 81\---栏位出现'*'   
 82If CHARINDEX('*',@Column_Name) &gt; 0   
 83Begin   
 84Select @Column_Name = ''   
 85Select @Loop_Seq = 1   
 86\---取栏位个数   
 87Select @Column_Count = Count(*)   
 88From SysColumns   
 89Where Id = Object_Id(@Table_name)   
 90While @Loop_Seq &lt;= @Column_Count   
 91Begin   
 92\---取栏位名称,栏位类型,长度,精度,小数位   
 93Select @Column_Name_Temp = SysColumns.Name,   
 94@Column_Type_Temp = Lower(SysTypes.Name),   
 95@Column_Length_Temp = SysColumns.Length,   
 96@Column_Xprec_Temp = SysColumns.Xprec,   
 97@Column_Xscale_Temp = SysColumns.Xscale   
 98From SysColumns,SysTypes   
 99Where SysColumns.Id = Object_Id(@Table_name) And   
100SysColumns.Colid = @Loop_Seq And   
101SysColumns.XuserType = SysTypes.XuserType   
102\---形成栏位语法表达式   
103Select @Column_Syntax_Temp = Case When @Column_Type_Temp In ('datetime','image','int') Then @Column_Name_Temp + ' ' + @Column_Type_Temp   
104When @Column_Type_Temp In ('binary','bit','char','varchar') Then @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(Varchar(10),@Column_Length_Temp) + ')'   
105Else @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(varchar(10),@Column_Xprec_Temp) + ',' + Convert(varchar(10),@Column_Xscale_Temp) + ')'   
106End   
107Select @Column_Syntax = @Column_Syntax + @Column_Syntax_Temp + ','   
108Select @Loop_Seq = @loop_Seq + 1   
109End   
110End   
111Else   
112Begin   
113\---取栏位名称   
114Select @Column_Name_Temp = @Column_Name   
115\---取栏位类型,长度,精度,小数位   
116Select @Column_Type_Temp = Lower(SysTypes.Name),   
117@Column_Length_Temp = Isnull(SysColumns.Length,0),   
118@Column_Xprec_Temp = Isnull(SysColumns.Xprec,0),   
119@Column_Xscale_Temp = Isnull(SysColumns.Xscale,0)   
120From SysColumns,SysTypes   
121Where SysColumns.Id = Object_Id(@Table_name) And   
122SysColumns.Name = @Column_Name_Temp And   
123SysColumns.XuserType = SysTypes.XuserType   
124\---形成栏位语法表达式   
125Select @Column_Syntax_Temp = Case When @Column_Type_Temp In ('datetime','image','int') Then @Column_Name_Temp + ' ' + @Column_Type_Temp   
126When @Column_Type_Temp In ('binary','bit','char','varchar') Then @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(Varchar(10),@Column_Length_Temp) + ')'   
127Else @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(varchar(10),@Column_Xprec_Temp) + ',' + Convert(varchar(10),@Column_Xscale_Temp) + ')'   
128End   
129Select @Column_Syntax = @Column_Syntax + @Column_Syntax_Temp + ',' 
130
131End   
132\---处理栏位列表   
133If @Temp_Pos &gt; 0   
134Begin   
135Select @Select_Command_Temp = Right(@Select_Command_Temp,Len(@Select_Command_Temp) - @Temp_Pos)   
136End   
137Else   
138Begin   
139Select @Select_Command_Temp = ''   
140End   
141End   
142\---形成正确的栏位创建语法   
143Select @Column_Syntax = Left(@Column_Syntax,Len(@Column_Syntax) - 1)   
144\---修改临时表的结构   
145Execute('Alter Table #Test Add '+@Column_Syntax)   
146Execute('Alter Table #Test Drop Column a')   
147\---将SELECT执行的结构集插入到临时表   
148Insert Into #Test   
149Execute(@Select_Command)   
150\---创建游标   
151Set @Cursor_Return = CURSOR LOCAL SCROLL READ_ONLY FOR   
152Select *   
153From #Test   
154\---打开游标   
155Open @Cursor_Return 
156
157▲使用游标 
158
159/注:在SELECT中有几项,fetch from @cursor_name into @cust_id就应该声明几个变量,而且顺序和类型必须一致.*/   
160declare @cursor_name cursor,   
161@select_command varchar(8000),   
162@cust_id varchar(20)   
163select @select_command = 'select cust_id from so_cust'   
164execute usp_createcursor @select_command,@cursor_name OUTPUT   
165fetch from @cursor_name into @cust_id   
166while @@fetch_status = 0   
167begin   
168fetch from @cursor_name into @cust_id   
169end   
170close @cursor_name   
171deallocate cursor_name 
172
173说明:上述代码在MSS SQL SERVER7.0上通过。其它数据库只需修改一下抓取栏位及其类型的系统表就可以了。</sql></table_name>
Published At
Categories with 数据库类
comments powered by Disqus