读书人

存储过程必须声明标量变量有关问题

发布时间: 2012-02-08 19:52:21 作者: rapoo

存储过程,必须声明标量变量问题
各位朋友
以下是我写的一个存储过程分页方法,能够编译通过,但是在使用时,老是提示“消息 137,级别 15,状态 1,第 1 行
必须声明标量变量 "@TotalCount "。”请看
CREATE PROCEDURE Pagination
@TotalCount INT OUTPUT,
@TotalPage INT OUTPUT,
@Table NVARCHAR(25), --将要查询的表名
@Column NVARCHAR(150),--将要查询的字段,可多列
@OrderColumn NVARCHAR(50), --排序字段
@CountColumn NVARCHAR(20), --取这个字段的最大值
@PageSize INT,--分页大小
@CurrentPage INT, --要查询的页
@OrderType NVARCHAR(4),--如何排序
@Condition NVARCHAR(200) --查询条件
AS
DECLARE @PageCount INT,
@strSql NVARCHAR(500),
@strCount NVARCHAR(100)
SET @PageCount=@PageSize*@CurrentPage
BEGIN
IF @Condition!= 'NO '
BEGIN
SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table + ' WHERE '+@Condition
SET @TotalPage=CEILING(str(@TotalCount/@PageSize))
SET @strSql= 'SELECT TOP '+ str(@PageSize) + ' '+ @Column + ' FROM '+ @Table + '
WHERE ' + @CountColumn + '> (SELECT MAX( '+ @CountColumn + ')
FROM (SELECT TOP ' + str(@PageCount)+ ' '+ @CountColumn+ '
FROM ' + @Table + ' ORDER BY ' + @CountColumn + ') AS T) AND '+ @Condition + ' ORDER BY ' + @OrderColumn + ' '+ @OrderType
END
ELSE
BEGIN
SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table
SET @TotalPage=CEILING(str(@TotalCount/@PageSize))
SET @strSql= 'SELECT TOP '+ str(@PageSize) + ' '+ @Column + ' FROM '+ @Table + '
WHERE ' + @CountColumn + '> (SELECT MAX( '+ @CountColumn + ')
FROM (SELECT TOP ' + str(@PageCount)+ ' '+ @CountColumn+ '
FROM ' + @Table + ' ORDER BY ' + @CountColumn + ') AS T)
ORDER BY ' + @OrderColumn + ' '+ @OrderType
END
EXEC (@strCount)
EXEC (@strSql)
END

下面是我在asp.net2.0中进行调用
public DataTable ShowBook(MShowBook mshowbook)
{
SqlParameter[] parms = new SqlParameter[10];
parms[0] = lzjbook.ParaInstance( "@Pagesize ", SqlDbType.Int, 4, mshowbook.Pagesize, ParameterDirection.Input);
parms[1] = lzjbook.ParaInstance( "@CurrentPage ", SqlDbType.Int, 4, mshowbook.CureentPage, ParameterDirection.Input);
parms[2] = lzjbook.ParaInstance( "@OrderType ", SqlDbType.NVarChar, 4, mshowbook.OrderType, ParameterDirection.Input);


parms[3] = lzjbook.ParaInstance( "@TotalCount ", SqlDbType.Int, 4, null, ParameterDirection.Output);
parms[4] = lzjbook.ParaInstance( "@TotalPage ", SqlDbType.Int, 4, null, ParameterDirection.Output);
parms[5] = lzjbook.ParaInstance( "@Table ", SqlDbType.NVarChar, 25, "MainBook ", ParameterDirection.Input);
parms[6] = lzjbook.ParaInstance( "@Column ", SqlDbType.NVarChar, 150, "BookName ", ParameterDirection.Input);
parms[7] = lzjbook.ParaInstance( "@OrderColumn ", SqlDbType.NVarChar, 50, "AddTime ", ParameterDirection.Input);
parms[8] = lzjbook.ParaInstance( "@CountColumn ", SqlDbType.NVarChar, 20, "BookID ", ParameterDirection.Input);
parms[9] = lzjbook.ParaInstance( "@Condition ", SqlDbType.NVarChar, 200, "bookname= '图书名 ' ", ParameterDirection.Input);
DataTable dt = new DataTable();
try
{
dt = lzjbook.GetOneRecord( "Pagination ", CommandType.StoredProcedure, parms);
}
catch (Exception e)
{
if (e != null)
{
HttpContext.Current.Response.Redirect( "Error.aspx?errorMsg=对不起,在函数执行期间出现了错误,给您带来不便表示歉意,请稍后再试! ");
}
}
finally
{
lzjbook.Close();
}


return dt;

}

参数都传进去,就是出现“消息 137,级别 15,状态 1,第 1 行
必须声明标量变量 "@TotalCount "。”
我的这个方法我测试过了,没有问题的
请各位帮我看看,感激不尽


[解决办法]
这句换下
EXEC (@strCount)
----------------------------------------------
exec sp_executesql @strCount,N 'TotalCount int output ',@TotalCount output
你这个属于动态sql带传出参数的.
可以参考下sp_executesql的用法.
[解决办法]
SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table + ' WHERE '+@Condition
SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table


上面两句要用sp_executesql才能把COUNT(*)结果提取出来。
[解决办法]
EXEC (@strCount)
EXEC (@strSql)
END

-- modify to
EXEC sp_executesql @strCount,N '@totalcount int output ',@totalcount output
EXEC (@strSql)
END



[解决办法]
--如何从动态SQL中返回数值?

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

declare @num int, @sql nvarchar(4000)
set @sql= 'select @a=count(*) from tableName '
exec sp_executesql @sql,N '@a int output ',@num output
select @num


[解决办法]

动态sql语句基本语法
1 :普通SQL语句可以用Exec执行

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

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

eg:
declare @fname varchar(20)
set @fname = 'FiledName '
Select @fname from tableName -- 错误,不会提示错误,但结果为固定值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, @sql nvarchar(4000)
set @sql= 'select count(*) from tableName '
exec(@sql)


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

declare @num int, @sql nvarchar(4000)
set @sql= 'select @a=count(*) from tableName '
exec sp_executesql @sql,N '@a int output ',@num output
select @num


[解决办法]
修改两处:

SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table + ' WHERE '+@Condition
exec sp_executesql @strCount, N '@TotalCount int output ', @TotalCount output
SET @TotalPage=CEILING(str(@TotalCount/@PageSize))

SET @strCount= 'SELECT @TotalCount=COUNT(*) FROM '+ @Table
exec sp_executesql @strCount, N '@TotalCount int output ', @TotalCount output


SET @TotalPage=CEILING(str(@TotalCount/@PageSize))

后面那一行:EXEC (@strCount),注释或删除。

读书人网 >SQL Server

热点推荐