分享
 
 
 

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

王朝mssql·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

▲创建游标

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 <TABLE_NAME> EXECUTE <SQL>,而SQL7.0的帮助未讲。有表有数据就可以创建了。

创建人: 康剑民

创建日期: 2001-07-11

*/

Declare @Select_Command_Temp Varchar(8000), ---存放SELECT临时语法

@Table_List varchar(255), ---存放表的列表

@Column_List varchar(8000),---存放栏位列表

@Table_Name varchar(30),---存放单独表名

@Column_Name varchar(30),---存放单独栏位名(但有可能是*)

@Column_Syntax varchar(8000),---存放栏位建表时的语法(综合)

@Column_Name_Temp varchar(30),---存放栏位名称

@Column_Type_Temp varchar(30),----存放栏位类型

@Column_Syntax_Temp varchar(8000),---存放栏位建表时的语法(单个)

@Column_Length_Temp int,---存放栏位长度

@Column_Xprec_Temp int,---存放栏位精度

@Column_Xscale_Temp int,---存放栏位小数位数

@From_Pos int,---存放from的位置

@Where_Pos int,---存放where的位置

@Having_Pos int,---存放having的位置

@Groupby_Pos int,---存放groupby的位置

@Orderby_Pos int,---存放orderby的位置

@Temp_Pos int,---临时变量

@Column_Count int,---存放栏位总数

@Loop_Seq int---循环步进变量

---创建临时表

Create Table #Test(a int)

---如果传来的SELECT语句不是以'select'开头,自动修改

If Left(Lower(Ltrim(@Select_Command)),6) <> 'select' Select @Select_Command = 'Select ' + @Select_Command

---将开头‘SELECT’去掉

Select @Select_Command_Temp = Lower(Ltrim(@Select_Command))

If Left(@Select_Command_Temp,6) = 'select' Select @Select_Command_Temp = Right(@Select_Command_Temp,Len(@Select_Command_Temp) - 7)

---取各保留字位置,以便获得表的列表

Select @From_Pos = CHARINDEX(' from ',@Select_Command_Temp)

Select @Where_Pos = CHARINDEX(' where ',@Select_Command_Temp)

Select @Having_Pos = CHARINDEX(' having ',@Select_Command_Temp)

Select @Groupby_Pos = CHARINDEX(' groupby ',@Select_Command_Temp)

Select @Orderby_Pos = CHARINDEX(' orderby ',@Select_Command_Temp)

If @Where_Pos > 0 Select @Temp_Pos = @Where_Pos

If @Having_Pos > 0 And @Having_Pos < @Temp_Pos Select @Temp_Pos = @Having_Pos

If @Groupby_Pos > 0 And @Groupby_Pos < @Temp_Pos Select @Temp_Pos = @Groupby_Pos

If @Orderby_Pos > 0 And @Orderby_Pos < @Temp_Pos Select @Temp_Pos = @Orderby_Pos

---取表列表

If @Temp_Pos > 0

Begin

Select @Table_List = SUBSTRING(@Select_Command_Temp,@From_Pos + 6 ,@Temp_Pos - @From_Pos - 1)

End

Else

Begin

Select @Table_List = SUBSTRING(@Select_Command_Temp,@From_Pos + 6 ,Len(@Select_Command_Temp) - @From_Pos - 1)

End

Select @Column_Syntax = ''

---只列出栏位

Select @Select_Command_Temp = Left(@Select_Command_Temp,@From_Pos - 1)

While Len(@Select_Command_Temp) > 0

Begin

---取逗号位置

Select @Temp_Pos = CHARINDEX(',',@Select_Command_Temp)

---初次取栏位名称

If @Temp_Pos > 0

Begin

Select @Column_Name = Left(@Select_Command_Temp,@Temp_Pos - 1)

End

Else

Begin

Select @Column_Name = @Select_Command_Temp

End

---取表名和栏位名(可能是‘*’)

If CHARINDEX('.',@Column_Name) > 0

Begin

Select @Table_Name = Left(@Column_Name,CHARINDEX('.',@Column_Name) - 1)

Select @Column_Name = Right(@Column_Name,Len(@Column_Name) - CHARINDEX('.',@Column_Name))

End

Else

Begin

Select @Table_Name = @Table_List

End

---栏位出现'*'

If CHARINDEX('*',@Column_Name) > 0

Begin

Select @Column_Name = ''

Select @Loop_Seq = 1

---取栏位个数

Select @Column_Count = Count(*)

From SysColumns

Where Id = Object_Id(@Table_name)

While @Loop_Seq <= @Column_Count

Begin

---取栏位名称,栏位类型,长度,精度,小数位

Select @Column_Name_Temp = SysColumns.Name,

@Column_Type_Temp = Lower(SysTypes.Name),

@Column_Length_Temp = SysColumns.Length,

@Column_Xprec_Temp = SysColumns.Xprec,

@Column_Xscale_Temp = SysColumns.Xscale

From SysColumns,SysTypes

Where SysColumns.Id = Object_Id(@Table_name) And

SysColumns.Colid = @Loop_Seq And

SysColumns.XuserType = SysTypes.XuserType

---形成栏位语法表达式

Select @Column_Syntax_Temp = Case When @Column_Type_Temp In ('datetime','image','int') Then @Column_Name_Temp + ' ' + @Column_Type_Temp

When @Column_Type_Temp In ('binary','bit','char','varchar') Then @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(Varchar(10),@Column_Length_Temp) + ')'

Else @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(varchar(10),@Column_Xprec_Temp) + ',' + Convert(varchar(10),@Column_Xscale_Temp) + ')'

End

Select @Column_Syntax = @Column_Syntax + @Column_Syntax_Temp + ','

Select @Loop_Seq = @loop_Seq + 1

End

End

Else

Begin

---取栏位名称

Select @Column_Name_Temp = @Column_Name

---取栏位类型,长度,精度,小数位

Select @Column_Type_Temp = Lower(SysTypes.Name),

@Column_Length_Temp = Isnull(SysColumns.Length,0),

@Column_Xprec_Temp = Isnull(SysColumns.Xprec,0),

@Column_Xscale_Temp = Isnull(SysColumns.Xscale,0)

From SysColumns,SysTypes

Where SysColumns.Id = Object_Id(@Table_name) And

SysColumns.Name = @Column_Name_Temp And

SysColumns.XuserType = SysTypes.XuserType

---形成栏位语法表达式

Select @Column_Syntax_Temp = Case When @Column_Type_Temp In ('datetime','image','int') Then @Column_Name_Temp + ' ' + @Column_Type_Temp

When @Column_Type_Temp In ('binary','bit','char','varchar') Then @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(Varchar(10),@Column_Length_Temp) + ')'

Else @Column_Name_Temp + ' ' + @Column_Type_Temp + '('+Convert(varchar(10),@Column_Xprec_Temp) + ',' + Convert(varchar(10),@Column_Xscale_Temp) + ')'

End

Select @Column_Syntax = @Column_Syntax + @Column_Syntax_Temp + ','

End

---处理栏位列表

If @Temp_Pos > 0

Begin

Select @Select_Command_Temp = Right(@Select_Command_Temp,Len(@Select_Command_Temp) - @Temp_Pos)

End

Else

Begin

Select @Select_Command_Temp = ''

End

End

---形成正确的栏位创建语法

Select @Column_Syntax = Left(@Column_Syntax,Len(@Column_Syntax) - 1)

---修改临时表的结构

Execute('Alter Table #Test Add '+@Column_Syntax)

Execute('Alter Table #Test Drop Column a')

---将SELECT执行的结构集插入到临时表

Insert Into #Test

Execute(@Select_Command)

---创建游标

Set @Cursor_Return = CURSOR LOCAL SCROLL READ_ONLY FOR

Select *

From #Test

---打开游标

Open @Cursor_Return

▲使用游标

/注:在SELECT中有几项,fetch from @cursor_name into @cust_id就应该声明几个变量,而且顺序和类型必须一致.*/

declare @cursor_name cursor,

@select_command varchar(8000),

@cust_id varchar(20)

select @select_command = 'select cust_id from so_cust'

execute usp_createcursor @select_command,@cursor_name OUTPUT

fetch from @cursor_name into @cust_id

while @@fetch_status = 0

begin

fetch from @cursor_name into @cust_id

end

close @cursor_name

deallocate cursor_name

说明:上述代码在MSS SQL SERVER7.0上通过。其它数据库只需修改一下抓取栏位及其类型的系统表就可以了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有