在动态查询中获取输出
Get output in dynamic query
我正在创建一个存储过程,我想在其中获取输出参数值。即 blow 查询中的 @RecordCount INT OUTPUT。但是我无法从低于 SP 的值中获取 OUTPUT 参数。
ALTER PROCEDURE [dbo].[GetOrderListByClient]
@PageIndex INT = 1
,@PageSize INT = 10
,@orderNumber varchar(15) = null,
@ref varchar(255) = null,
@OrderstartDate date = null ,
@OrderEndDate date= null ,
@ClientId varchar(1000) ,
@RecordCount INT OUTPUT
AS
BEGIN
IF @OrderEndDate IS NULL Or @OrderEndDate = ''
SET @OrderEndDate =CONVERT(Varchar(14), GETDATE(),101)
SET @OrderstartDate = CONVERT(varchar(10),@OrderstartDate,101)
SET @OrderEndDate =CONVERT(VARCHAR(10),@OrderEndDate,101)
SET NOCOUNT ON;
DECLARE @QUERY VARCHAR(MAX)
DECLARE @FINALQUERY VARCHAR(MAX)
DECLARE @QUERY2 VARCHAR(MAX)
SET @QUERY =
'
DECLARE @temp table
(
RowNumber int ,
ORDERID int,
ORDERNUM varchar(15) NULL,
READYDATE date NULL,
ref varchar(255) NULL,
PADDR varchar(40) NULL,
DADDR varchar(40) NULL,
DCity varchar(25) NULL,
readyTime datetime2(7) NULL,
PICKTIME time null,
DRV1ID int null,
TOTAL decimal(10,2) NULL,
DeliveryTime time null,
PCITY varchar(40) null,
PICKUP varchar(40) null,
DROPOFF varchar(40) null,
PICTURECOUNT int
)
INSERT INTO @temp
SELECT ROW_NUMBER() OVER
(
ORDER BY [ORDERNUM] DESC
)AS RowNumber
,O.ORDERID, O.ORDERNUM, CONVERT(VARCHAR(11),CAST(O.READYDATE as DATE) ) AS READYDATE,O.Ref,O.PADDR,O.DADDR,
O.DCity,CONVERT(VARCHAR(5),O.readyTime,14)AS readyTime,CONVERT (VARCHAR(5),CAST(O.PICKTIME as Time)) AS PICKTIME,
O.DRV1ID,O.TOTAL,CONVERT (VARCHAR(5),CAST(O.DELIVERBY as Time)) AS DeliveryTime,PCITY,PICKUP,DROPOFF,O.PICTURECOUNT
--INTO @temp
from Orde_ O
WHERE '
IF (@QUERY <>'')
SET @QUERY = @QUERY + ' CANCELLED = 0 '
ELSE
SET @QUERY = @QUERY + ' AND CANCELLED = 0 '
IF (@QUERY2 ='')
SET @QUERY = @QUERY + ' CLIENTID IN (' + @ClientId +')'
ELSE
SET @QUERY = @QUERY + ' AND CLIENTID IN (' + @ClientId +')'
--if( @orderNumber <>'')
-- SET @QUERY2 = @QUERY + ' AND ORDERNUM = '''+ @orderNumber+''
IF (@ref <> '')
BEGIN
IF @QUERY2 = ''
SET @QUERY = @QUERY + ' REF Like %'''+ @ref + '%'''
ELSE
SET @QUERY = @QUERY + ' AND REF Like %'''+ @ref+ '%'''
END
-- AND ((READYDATE BETWEEN '''+ CONVERT(VARCHAR(10), @OrderstartDate,101)+''' AND '''+ CONVERT(VARCHAR(10),@OrderEndDate,101)+''') OR ( '+ CONVERT(VARCHAR(10), @OrderstartDate,101)+' IS NULL OR READYDATE >= '''+ CONVERT(VARCHAR(10),@OrderstartDate,101)+''' )
-- AND ('''+ CONVERT(VARCHAR(10), @OrderEndDate,101)+''' IS NULL OR READYDATE <= '''+CONVERT(VARCHAR(10),@OrderEndDate,101)+'''))) '
SET @QUERY = @QUERY + '
SELECT @RecordCount= COUNT(1) FROM @temp
SELECT * FROM @temp
WHERE RowNumber BETWEEN ( '+ CONVERT(VARCHAR(20), @PageIndex) +' -1) * '+ CONVERT(VARCHAR(20),@PageSize) +' + 1 AND((( '+ CONVERT(VARCHAR(10),@PageIndex)+' -1) * '+ CONVERT(VARCHAR(10),@PageSize)+' + 1) + '+ CONVERT(VARCHAR(10),@PageSize)+') - 1 '
PRINT @QUERY
--exec (@QUERY)
-- Execute sp_Executesql @Query , @PageIndex,@PageSize,@OrderstartDate,@OrderEndDate,@ClientId, @RecordCount OUTPUT
-- DROP TABLE #Results
END
请尝试以下查询,让我知道问题是否已解决。
ALTER PROCEDURE [dbo].[GetOrderListByClient] @PageIndex INT = 1
,@PageSize INT = 10
,@orderNumber VARCHAR(15) = NULL
,@ref VARCHAR(255) = NULL
,@OrderstartDate DATE = NULL
,@OrderEndDate DATE = NULL
,@ClientId VARCHAR(1000)
,@RecordCount INT OUTPUT
AS
BEGIN
IF @OrderEndDate IS NULL
OR @OrderEndDate = ''
SET @OrderEndDate = CONVERT(VARCHAR(14), GETDATE(), 101)
SET @OrderstartDate = CONVERT(VARCHAR(10), @OrderstartDate, 101)
SET @OrderEndDate = CONVERT(VARCHAR(10), @OrderEndDate, 101)
SET NOCOUNT ON;
DECLARE @QUERY VARCHAR(MAX)
DECLARE @FINALQUERY VARCHAR(MAX)
DECLARE @QUERY2 VARCHAR(MAX)
SET @QUERY =
'
DECLARE @temp table
(
RowNumber int ,
ORDERID int,
ORDERNUM varchar(15) NULL,
READYDATE date NULL,
ref varchar(255) NULL,
PADDR varchar(40) NULL,
DADDR varchar(40) NULL,
DCity varchar(25) NULL,
readyTime datetime2(7) NULL,
PICKTIME time null,
DRV1ID int null,
TOTAL decimal(10,2) NULL,
DeliveryTime time null,
PCITY varchar(40) null,
PICKUP varchar(40) null,
DROPOFF varchar(40) null,
PICTURECOUNT int
)
INSERT INTO @temp
SELECT ROW_NUMBER() OVER
(
ORDER BY [ORDERNUM] DESC
)AS RowNumber
,O.ORDERID, O.ORDERNUM, CONVERT(VARCHAR(11),CAST(O.READYDATE as DATE) ) AS READYDATE,O.Ref,O.PADDR,O.DADDR,
O.DCity,CONVERT(VARCHAR(5),O.readyTime,14)AS readyTime,CONVERT (VARCHAR(5),CAST(O.PICKTIME as Time)) AS PICKTIME,
O.DRV1ID,O.TOTAL,CONVERT (VARCHAR(5),CAST(O.DELIVERBY as Time)) AS DeliveryTime,PCITY,PICKUP,DROPOFF,O.PICTURECOUNT
--INTO @temp
from Orde_ O
WHERE '
IF (@QUERY <> '')
SET @QUERY = @QUERY + ' CANCELLED = 0 '
ELSE
SET @QUERY = @QUERY + ' AND CANCELLED = 0 '
IF (@QUERY2 = '')
SET @QUERY = @QUERY + ' CLIENTID IN (' + @ClientId + ')'
ELSE
SET @QUERY = @QUERY + ' AND CLIENTID IN (' + @ClientId + ')'
--if( @orderNumber <>'')
-- SET @QUERY2 = @QUERY + ' AND ORDERNUM = '''+ @orderNumber+''
IF (@ref <> '')
BEGIN
IF @QUERY2 = ''
SET @QUERY = @QUERY + ' REF Like %''' + @ref + '%'''
ELSE
SET @QUERY = @QUERY + ' AND REF Like %''' + @ref + '%'''
END
-- AND ((READYDATE BETWEEN '''+ CONVERT(VARCHAR(10), @OrderstartDate,101)+''' AND '''+ CONVERT(VARCHAR(10),@OrderEndDate,101)+''') OR ( '+ CONVERT(VARCHAR(10), @OrderstartDate,101)+' IS NULL OR READYDATE >= '''+ CONVERT(VARCHAR(10),@OrderstartDate,101)+''' )
-- AND ('''+ CONVERT(VARCHAR(10), @OrderEndDate,101)+''' IS NULL OR READYDATE <= '''+CONVERT(VARCHAR(10),@OrderEndDate,101)+'''))) '
SET @QUERY = @QUERY + '
SELECT @RecordCount= COUNT(1) FROM @temp ' + '
SELECT * FROM @temp
WHERE RowNumber BETWEEN (' + '+ CONVERT(VARCHAR(20), @PageIndex) ' + ' -1) * ' + ' CONVERT(VARCHAR(20),@PageSize)' + ' 1 AND((( ' + 'CONVERT(VARCHAR(10),@PageIndex)' + ' -1) * ' + ' CONVERT(VARCHAR(10),@PageSize)' + ' 1) ' + '+ CONVERT(VARCHAR(10),@PageSize)' + ') - 1 '
--PRINT @QUERY
exec (@QUERY)
Execute sp_Executesql @Query , @PageIndex,@PageSize,@OrderstartDate,@OrderEndDate,@ClientId, @RecordCount OUTPUT
-- DROP TABLE #Results
END
这是一个示例查询,但是,它应该能让您走上正确的道路。以上是一个巨大的安全问题,需要修复。您的查询中没有任何动态对象,您只使用动态 SQL 因为查询是 "Catch-all Query"。这种方法适用于此类查询(我个人推荐它),但您必须 参数化您的查询(同样,Dos and Don'ts of Dynamic SQL)。
下面的这个查询至少向您展示了如何使用 OUTPUT 参数创建动态查询:
CREATE TABLE dbo.YourTable (ID int IDENTITY,
SomeString varchar(25),
SomeInt int)
GO
CREATE PROC dbo.YourProc @SomeString varchar(25) = NULL, @SomeInt int = NULL, @RowCount int OUTPUT AS
BEGIN
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET @SQL = N'SELECT @RowCount = COUNT(*)' + @CRLF +
N'FROM dbo.YourTable' + @CRLF +
CASE WHEN @SomeString IS NOT NULL OR @SomeInt IS NOT NULL
THEN N'WHERE ' + STUFF(CASE WHEN @SomeString IS NOT NULL THEN @CRLF + N' AND SomeString = @SomeString' ELSE N'' END +
CASE WHEN @SomeInt IS NOT NULL THEN @CRLF + N' AND SomeInt = @SomeInt' ELSE N''END,1,8,N'')
ELSE ''
END + N';';
--PRINT @SQL; --Your debugging best friend.
--You'll need SELECT for queries over 4,000 characters (but don't leave that (uncommented) in your SP!
EXEC sp_executesql @SQL, N'@SomeString varchar(25), @SomeInt int, @RowCount int OUTPUT', @SomeString, @SomeInt, @RowCount OUTPUT;
END;
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = NULL,
@SomeInt = NULL,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --0
GO
INSERT INTO dbo.YourTable (SomeString,
SomeInt)
VALUES('sdfgsdfg',1),
('sdfjhsdgfs',1),
('sdfgkhjdfbgk',2);
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = NULL,
@SomeInt = 1,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --2
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = 'sdfjhsdgfs',
@SomeInt = 1,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --1
GO
DROP PROC dbo.YourProc;
DROP TABLE dbo.YourTable;
我正在创建一个存储过程,我想在其中获取输出参数值。即 blow 查询中的 @RecordCount INT OUTPUT。但是我无法从低于 SP 的值中获取 OUTPUT 参数。
ALTER PROCEDURE [dbo].[GetOrderListByClient]
@PageIndex INT = 1
,@PageSize INT = 10
,@orderNumber varchar(15) = null,
@ref varchar(255) = null,
@OrderstartDate date = null ,
@OrderEndDate date= null ,
@ClientId varchar(1000) ,
@RecordCount INT OUTPUT
AS
BEGIN
IF @OrderEndDate IS NULL Or @OrderEndDate = ''
SET @OrderEndDate =CONVERT(Varchar(14), GETDATE(),101)
SET @OrderstartDate = CONVERT(varchar(10),@OrderstartDate,101)
SET @OrderEndDate =CONVERT(VARCHAR(10),@OrderEndDate,101)
SET NOCOUNT ON;
DECLARE @QUERY VARCHAR(MAX)
DECLARE @FINALQUERY VARCHAR(MAX)
DECLARE @QUERY2 VARCHAR(MAX)
SET @QUERY =
'
DECLARE @temp table
(
RowNumber int ,
ORDERID int,
ORDERNUM varchar(15) NULL,
READYDATE date NULL,
ref varchar(255) NULL,
PADDR varchar(40) NULL,
DADDR varchar(40) NULL,
DCity varchar(25) NULL,
readyTime datetime2(7) NULL,
PICKTIME time null,
DRV1ID int null,
TOTAL decimal(10,2) NULL,
DeliveryTime time null,
PCITY varchar(40) null,
PICKUP varchar(40) null,
DROPOFF varchar(40) null,
PICTURECOUNT int
)
INSERT INTO @temp
SELECT ROW_NUMBER() OVER
(
ORDER BY [ORDERNUM] DESC
)AS RowNumber
,O.ORDERID, O.ORDERNUM, CONVERT(VARCHAR(11),CAST(O.READYDATE as DATE) ) AS READYDATE,O.Ref,O.PADDR,O.DADDR,
O.DCity,CONVERT(VARCHAR(5),O.readyTime,14)AS readyTime,CONVERT (VARCHAR(5),CAST(O.PICKTIME as Time)) AS PICKTIME,
O.DRV1ID,O.TOTAL,CONVERT (VARCHAR(5),CAST(O.DELIVERBY as Time)) AS DeliveryTime,PCITY,PICKUP,DROPOFF,O.PICTURECOUNT
--INTO @temp
from Orde_ O
WHERE '
IF (@QUERY <>'')
SET @QUERY = @QUERY + ' CANCELLED = 0 '
ELSE
SET @QUERY = @QUERY + ' AND CANCELLED = 0 '
IF (@QUERY2 ='')
SET @QUERY = @QUERY + ' CLIENTID IN (' + @ClientId +')'
ELSE
SET @QUERY = @QUERY + ' AND CLIENTID IN (' + @ClientId +')'
--if( @orderNumber <>'')
-- SET @QUERY2 = @QUERY + ' AND ORDERNUM = '''+ @orderNumber+''
IF (@ref <> '')
BEGIN
IF @QUERY2 = ''
SET @QUERY = @QUERY + ' REF Like %'''+ @ref + '%'''
ELSE
SET @QUERY = @QUERY + ' AND REF Like %'''+ @ref+ '%'''
END
-- AND ((READYDATE BETWEEN '''+ CONVERT(VARCHAR(10), @OrderstartDate,101)+''' AND '''+ CONVERT(VARCHAR(10),@OrderEndDate,101)+''') OR ( '+ CONVERT(VARCHAR(10), @OrderstartDate,101)+' IS NULL OR READYDATE >= '''+ CONVERT(VARCHAR(10),@OrderstartDate,101)+''' )
-- AND ('''+ CONVERT(VARCHAR(10), @OrderEndDate,101)+''' IS NULL OR READYDATE <= '''+CONVERT(VARCHAR(10),@OrderEndDate,101)+'''))) '
SET @QUERY = @QUERY + '
SELECT @RecordCount= COUNT(1) FROM @temp
SELECT * FROM @temp
WHERE RowNumber BETWEEN ( '+ CONVERT(VARCHAR(20), @PageIndex) +' -1) * '+ CONVERT(VARCHAR(20),@PageSize) +' + 1 AND((( '+ CONVERT(VARCHAR(10),@PageIndex)+' -1) * '+ CONVERT(VARCHAR(10),@PageSize)+' + 1) + '+ CONVERT(VARCHAR(10),@PageSize)+') - 1 '
PRINT @QUERY
--exec (@QUERY)
-- Execute sp_Executesql @Query , @PageIndex,@PageSize,@OrderstartDate,@OrderEndDate,@ClientId, @RecordCount OUTPUT
-- DROP TABLE #Results
END
请尝试以下查询,让我知道问题是否已解决。
ALTER PROCEDURE [dbo].[GetOrderListByClient] @PageIndex INT = 1
,@PageSize INT = 10
,@orderNumber VARCHAR(15) = NULL
,@ref VARCHAR(255) = NULL
,@OrderstartDate DATE = NULL
,@OrderEndDate DATE = NULL
,@ClientId VARCHAR(1000)
,@RecordCount INT OUTPUT
AS
BEGIN
IF @OrderEndDate IS NULL
OR @OrderEndDate = ''
SET @OrderEndDate = CONVERT(VARCHAR(14), GETDATE(), 101)
SET @OrderstartDate = CONVERT(VARCHAR(10), @OrderstartDate, 101)
SET @OrderEndDate = CONVERT(VARCHAR(10), @OrderEndDate, 101)
SET NOCOUNT ON;
DECLARE @QUERY VARCHAR(MAX)
DECLARE @FINALQUERY VARCHAR(MAX)
DECLARE @QUERY2 VARCHAR(MAX)
SET @QUERY =
'
DECLARE @temp table
(
RowNumber int ,
ORDERID int,
ORDERNUM varchar(15) NULL,
READYDATE date NULL,
ref varchar(255) NULL,
PADDR varchar(40) NULL,
DADDR varchar(40) NULL,
DCity varchar(25) NULL,
readyTime datetime2(7) NULL,
PICKTIME time null,
DRV1ID int null,
TOTAL decimal(10,2) NULL,
DeliveryTime time null,
PCITY varchar(40) null,
PICKUP varchar(40) null,
DROPOFF varchar(40) null,
PICTURECOUNT int
)
INSERT INTO @temp
SELECT ROW_NUMBER() OVER
(
ORDER BY [ORDERNUM] DESC
)AS RowNumber
,O.ORDERID, O.ORDERNUM, CONVERT(VARCHAR(11),CAST(O.READYDATE as DATE) ) AS READYDATE,O.Ref,O.PADDR,O.DADDR,
O.DCity,CONVERT(VARCHAR(5),O.readyTime,14)AS readyTime,CONVERT (VARCHAR(5),CAST(O.PICKTIME as Time)) AS PICKTIME,
O.DRV1ID,O.TOTAL,CONVERT (VARCHAR(5),CAST(O.DELIVERBY as Time)) AS DeliveryTime,PCITY,PICKUP,DROPOFF,O.PICTURECOUNT
--INTO @temp
from Orde_ O
WHERE '
IF (@QUERY <> '')
SET @QUERY = @QUERY + ' CANCELLED = 0 '
ELSE
SET @QUERY = @QUERY + ' AND CANCELLED = 0 '
IF (@QUERY2 = '')
SET @QUERY = @QUERY + ' CLIENTID IN (' + @ClientId + ')'
ELSE
SET @QUERY = @QUERY + ' AND CLIENTID IN (' + @ClientId + ')'
--if( @orderNumber <>'')
-- SET @QUERY2 = @QUERY + ' AND ORDERNUM = '''+ @orderNumber+''
IF (@ref <> '')
BEGIN
IF @QUERY2 = ''
SET @QUERY = @QUERY + ' REF Like %''' + @ref + '%'''
ELSE
SET @QUERY = @QUERY + ' AND REF Like %''' + @ref + '%'''
END
-- AND ((READYDATE BETWEEN '''+ CONVERT(VARCHAR(10), @OrderstartDate,101)+''' AND '''+ CONVERT(VARCHAR(10),@OrderEndDate,101)+''') OR ( '+ CONVERT(VARCHAR(10), @OrderstartDate,101)+' IS NULL OR READYDATE >= '''+ CONVERT(VARCHAR(10),@OrderstartDate,101)+''' )
-- AND ('''+ CONVERT(VARCHAR(10), @OrderEndDate,101)+''' IS NULL OR READYDATE <= '''+CONVERT(VARCHAR(10),@OrderEndDate,101)+'''))) '
SET @QUERY = @QUERY + '
SELECT @RecordCount= COUNT(1) FROM @temp ' + '
SELECT * FROM @temp
WHERE RowNumber BETWEEN (' + '+ CONVERT(VARCHAR(20), @PageIndex) ' + ' -1) * ' + ' CONVERT(VARCHAR(20),@PageSize)' + ' 1 AND((( ' + 'CONVERT(VARCHAR(10),@PageIndex)' + ' -1) * ' + ' CONVERT(VARCHAR(10),@PageSize)' + ' 1) ' + '+ CONVERT(VARCHAR(10),@PageSize)' + ') - 1 '
--PRINT @QUERY
exec (@QUERY)
Execute sp_Executesql @Query , @PageIndex,@PageSize,@OrderstartDate,@OrderEndDate,@ClientId, @RecordCount OUTPUT
-- DROP TABLE #Results
END
这是一个示例查询,但是,它应该能让您走上正确的道路。以上是一个巨大的安全问题,需要修复。您的查询中没有任何动态对象,您只使用动态 SQL 因为查询是 "Catch-all Query"。这种方法适用于此类查询(我个人推荐它),但您必须 参数化您的查询(同样,Dos and Don'ts of Dynamic SQL)。
下面的这个查询至少向您展示了如何使用 OUTPUT 参数创建动态查询:
CREATE TABLE dbo.YourTable (ID int IDENTITY,
SomeString varchar(25),
SomeInt int)
GO
CREATE PROC dbo.YourProc @SomeString varchar(25) = NULL, @SomeInt int = NULL, @RowCount int OUTPUT AS
BEGIN
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET @SQL = N'SELECT @RowCount = COUNT(*)' + @CRLF +
N'FROM dbo.YourTable' + @CRLF +
CASE WHEN @SomeString IS NOT NULL OR @SomeInt IS NOT NULL
THEN N'WHERE ' + STUFF(CASE WHEN @SomeString IS NOT NULL THEN @CRLF + N' AND SomeString = @SomeString' ELSE N'' END +
CASE WHEN @SomeInt IS NOT NULL THEN @CRLF + N' AND SomeInt = @SomeInt' ELSE N''END,1,8,N'')
ELSE ''
END + N';';
--PRINT @SQL; --Your debugging best friend.
--You'll need SELECT for queries over 4,000 characters (but don't leave that (uncommented) in your SP!
EXEC sp_executesql @SQL, N'@SomeString varchar(25), @SomeInt int, @RowCount int OUTPUT', @SomeString, @SomeInt, @RowCount OUTPUT;
END;
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = NULL,
@SomeInt = NULL,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --0
GO
INSERT INTO dbo.YourTable (SomeString,
SomeInt)
VALUES('sdfgsdfg',1),
('sdfjhsdgfs',1),
('sdfgkhjdfbgk',2);
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = NULL,
@SomeInt = 1,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --2
GO
DECLARE @RowCount int;
EXEC dbo.YourProc @SomeString = 'sdfjhsdgfs',
@SomeInt = 1,
@RowCount = @RowCount OUTPUT;
SELECT @RowCount; --1
GO
DROP PROC dbo.YourProc;
DROP TABLE dbo.YourTable;