求助:存储过程中如何将变量表的count,min,max结果存储到变量中
假如表名是静态的,则在存储过程中执行如下代码:
select @cnt=count(1) from AAA
是正确的.
但假如表名是变量,则在存储过程中执行如下代码:
select @tbname='AAA' + @Avariable
select @sqlstr='select @cnt=count(1) from ' + @tbname
exec(@sqlstr)
将是错误的.
请教我如何获得表@tbname的记录数,要求不建立临时表.谢谢!
错误产生的原因是exec语句的作用范围之在exec()之内.
假如用户现在是在数据库A下面,同时数据库A里面有表1,但数据库B下面没有表1,以下的SQL仍然能正确执行.
use A exec(use b) select * from 表1
不知道楼上这位为什么如此反感临时表,只不过加多一行就可以解决问题.
把上面的SQL改改
select @sqlstr='select count(1) a from' + @tbname
insert into #a exec(@sqlstr)
select @cnt=a from#a
要是真的有不想用临时表又不嫌麻烦干脆用@@rowcount解决算了.
select @sqlstr='select 1 from ' +@tbname
exec (@sqlstr)
select @cnt =@@rowcount
照样可以搞顶,不过不大理解为什么楼主不用temp table,是不是以为用temp一定要先创建才可以的?嘿嘿.
之所以不用临时表,是因为该存储过程被调用的频率相当高,影响到效率.我现在就是用的临时表来处理,有时在高峰时会发生数据库锁表的现象.所以才请教不用创建临时表的做法.
现在我是这样做的:
create table #A(cnt int)
select sqlstr='insert into #A select count(1) from ' + @tbname
select @cnt=cnt from #A
drop table #A.
楼上说的
select @sqlstr='select * from ' +@tbname
exec (@sqlstr)
select @cnt =@@rowcount
这种方式不可行,因为如果表@tbname记录太多,更影响效率.
临时表应该不是影响效率的主要原因, 相对于min,max,count(1)等语句,创建临时表所花的effort可以忽略不计,方法况且临时表是相对于每个session的,照理说不同session之间应该不会发生temp table的死锁才对(以前没遇见过sybase有这种情况,我们sybase存储过程调用频率也很高的, 不过没发生过兄弟遇见的这种情况, 也许是别的东西导致的),而且存储过程的调用频率如果高到某种程度的话,我觉得设计方面可以稍微做下改动的了,比如min, max, count等东东不一定要到用户触发stored procedure的时候才开始去生成, 而应该时先准备好, 减少服务器负载.
还有不知道你这样写结果能否出来,
create table #A(cnt int)
select sqlstr='insert into #A select count(1) from ' + @tbname
在这里如果你用exec(@sqlstr)的话应该临时表#A的生命周期也只是在exec()里面, 你应该没办法从下面的语句中拿到@cnt(嘿嘿, 在家里也没sybase试,不知道说得对不对)
select @cnt=cnt from #A
drop table #A.
顺便, 关于死锁的问题, 尽量用隔离级别低的锁, 比如行锁(Sybase里面default的锁应该是rowlock);尽量使用相同的存取顺序来处理事务,也就是如果可能的话大家写程序都有意识地访问完a表再访问b表,不要一个程序里面读a先,另外一个却读b表先...
^_^
临时表#A在exec(@sqlstr)后,仍然有效,因为它是SESSION级的.这点已经在实际应用试过了,可行.
后来,我将drop table #A语句删除,就再没有出现过数据库锁表的现象,不知道是为什么?
现在我准备将它改造成临时存储过程的方式来实现,不知道哪种方式更好?还望赐教!!
declare @tablename varchar(20)
declare @Avariable varchar(10)
declare @cnt int
declare @sqlstr varchar(100)
select @Avariable = '101'
select @tablename = 'AAA' + @Avariable
select @sqlstr='create procedure p_temp_cnt @cnt int output as select @cnt=count(*) from '+@tablename
exec(@sqlstr)
exec p_temp_cnt @cnt out
drop proc p_temp_cnt