不能在sp_executesql

时间:2016-11-22 07:41:11

标签: sql sql-server

我的SP中有这个代码:

ALTER PROCEDURE [dbo].[API_LIST_CONTENT_TEST]
@Page int,
@PageSize int = 20,
@TotalPage int Output
AS
BEGIN
SET NOCOUNT ON

-- PAGING --
DECLARE @FirstPage INT, @LastPage INT, @TotalRecord MONEY
SELECT  @FirstPage = (@Page - 1) * @PageSize,
        @LastPage = (@Page * @PageSize) + 1,
        @TotalPage = 0,
        @TotalRecord = 0

-- DATA --
CREATE TABLE #Data(
    ID INT IDENTITY(1,1) NOT NULL,
    Distance INT
)

DECLARE @TodayOpen nvarchar(100), @TodayClose nvarchar(100), @SQLSELECT NVARCHAR(MAX)
SELECT @TodayOpen = DATENAME(dw,GETDATE())+'Open', @TodayClose = DATENAME(dw,GETDATE())+'Close', @SQLSELECT = ''

SELECT @TotalRecord = COUNT(1) FROM #Data
SELECT @TotalPage = CASE WHEN @TotalRecord = 0 THEN 0 ELSE CEILING(@TotalRecord/@PageSize) END

SELECT @SQLSELECT = N'
SELECT 
    B.[Address],
    B.'+ @todayOpen +',
    B.'+ @todayClose +'
FROM #Data D
    INNER JOIN dbo.Bis B WITH (NOLOCK) ON D.BizID = B.BizID
    LEFT JOIN dbo.Category C WITH (NOLOCK) ON B.FIDCategory = C.CategoryID
WHERE B.[Status] = 3 AND ID > '+ @FirstPage +' 
ORDER BY ID'

EXEC (@SQLSELECT)

DROP TABLE #Data

END

结果例外:

  

“转换nvarchar值时转换失败   选择   B.FIDCategory,......   ....在哪里B. [状态] = 3 AND ID> “   数据类型int。

无法在SQLSELECT上读取@FirstPage,为什么?

我是First Grad Programmer,所以感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

在创建动态查询时需要将@FirstPage变量从int转换为Varchar,并将字符串值设置为@SQLSELECT varchar变量,因此不允许在其中设置INT值。

您的SP看起来像

ALTER PROCEDURE [dbo].[API_LIST_CONTENT_TEST]
@Page int,
@PageSize int = 20,
@TotalPage int Output
AS
BEGIN
SET NOCOUNT ON

-- PAGING --
DECLARE @FirstPage INT, @LastPage INT, @TotalRecord MONEY
SELECT  @FirstPage = (@Page - 1) * @PageSize,
        @LastPage = (@Page * @PageSize) + 1,
        @TotalPage = 0,
        @TotalRecord = 0

-- DATA --
CREATE TABLE #Data(
    ID INT IDENTITY(1,1) NOT NULL,
    Distance INT
)

DECLARE @TodayOpen nvarchar(100), @TodayClose nvarchar(100), @SQLSELECT NVARCHAR(MAX)
SELECT @TodayOpen = DATENAME(dw,GETDATE())+'Open', @TodayClose = DATENAME(dw,GETDATE())+'Close', @SQLSELECT = ''

SELECT @TotalRecord = COUNT(1) FROM #Data
SELECT @TotalPage = CASE WHEN @TotalRecord = 0 THEN 0 ELSE CEILING(@TotalRecord/@PageSize) END

SELECT @SQLSELECT = N'
SELECT 
    B.[Address],
    B.'+ @todayOpen +',
    B.'+ @todayClose +'
FROM #Data D
    INNER JOIN dbo.Bis B WITH (NOLOCK) ON D.BizID = B.BizID
    LEFT JOIN dbo.Category C WITH (NOLOCK) ON B.FIDCategory = C.CategoryID
WHERE B.[Status] = 3 AND ID > '+ Convert(Varchar(10),@FirstPage) +' 
ORDER BY ID'

EXEC (@SQLSELECT)

DROP TABLE #Data

END

答案 1 :(得分:1)

更好的解决方案是保持INT并将其作为参数传递:

SET SQLSELECT = N'
SELECT 
    B.[Address],
    B.'+ @todayOpen +',
    B.'+ @todayClose +'
FROM #Data D
    INNER JOIN dbo.Bis B WITH (NOLOCK) ON D.BizID = B.BizID
    LEFT JOIN dbo.Category C WITH (NOLOCK) ON B.FIDCategory = C.CategoryID
WHERE B.[Status] = 3 AND ID > @FirstPage
ORDER BY ID'

EXEC sp_executesql @SQLSELECT, N'@FirstPage INT', @FirstPage