Asp.net SQL Server存储过程临时表中的动态Where条件

Asp.net SQL Server存储过程临时表中的动态Where条件,asp.net,sql-server,stored-procedures,Asp.net,Sql Server,Stored Procedures,我正在使用ASP.NET和SQL Server数据库 我可以根据一些条件从gridview中搜索值。这些标准大多相互独立 例如: "where ProductType = " + Convert.ToInt32(recordType.persoRecord) + " and AccountNumber like '%" + SearchValue + "%'"; WHERE AccountNumber LIKE '%" + SearchValue + "%'" 或 有很多选项可供用户搜索。

我正在使用ASP.NET和SQL Server数据库

我可以根据一些条件从gridview中搜索值。这些标准大多相互独立

例如:

"where ProductType = " + Convert.ToInt32(recordType.persoRecord) + 
" and AccountNumber like '%" + SearchValue + "%'";
WHERE AccountNumber LIKE '%" + SearchValue + "%'"

有很多选项可供用户搜索。我在这个表中有数百万行数据,为了获取数据并将其快速绑定到gridview,我创建了一个存储过程

它可以很好地用于抓取和绑定,但是对于搜索,它很难管理。由于时间不多,我想将存储过程配置为“如果有搜索”,只获取搜索到的数据

以下是我的存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SetJobsGrid]
    (@FileID varchar(50),
     @PageIndex int = 1,
     @PageSize int = 1,
     @DynamicQuery  NVARCHAR(MAX),
     @SearchFlag bit,
     @RecordCount int output)
AS
BEGIN
    DECLARE @SearchQuerySQL as nvarchar(MAX)

    SET NOCOUNT ON;

    select ROW_NUMBER()OVER (
         order by j.creationdate asc,
                            j.id desc
    ) AS RowNumber
    ,  j.id as 'Serial #', j.jobname as 'File Record Name', 
                                j.RecordNumber as 'Record Number',i.issuername as'Issuer Name',p.ProductName as 'Product Name',p.productNumber as 'Product Number', 
                                (j.AccountNumber) as AccountNumber ,j.CardHolderName as 'Card Holder Name', j.CardholdersBranchName as 'Card Holder Branch Name', 
                                j.ShipmentBranchName as 'Shipment Branch Name', j.EmbossingCardholderName as 'Embossing Card Holder Name', j.MaskedPAN as 'PAN',
                                j.creationdate as 'File Record Creation Date', j.status as 'File Record Status', j.chipdatastatuserror as 'ChipDataStatus Erro', 
                                j.chipdatastatuserrormessage as 'Error Message', j.chipdatastatus as 'Data Prepared',j.isduplicaterecord as 'isduplicate',j.isduplicatefromsamefile as 'IsDuplicateFromSameFile',
                                j.validationerrors , j.isworkordercreatedForCard,j.isworkordercreatedForPin,j.isworkordercreatedForCarrier,j.PersoMachineId,j.PinMachineId,j.CarrierMachineId
                                INTO #Results
                                FROM  jobs j join issuer i on j.issuerid=i.id join Product p on p.id=j.productid WHERE fileid = @FileID

        IF(@SearchFlag = 1)
            begin
                select @SearchQuerySQL = 'SELECT ' + @RecordCount + ' = COUNT(*) FROM #Results ' + @DynamicQuery 

                EXEC(@SearchQuerySQL)

                select @SearchQuerySQL = 'SELECT * FROM #Results ' + @DynamicQuery + ' and RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1'

                EXEC(@SearchQuerySQL)

            end
        ELSE
            begin
                SELECT @RecordCount = COUNT(*)
                FROM #Results

                SELECT * FROM #Results
                WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1
            end

    DROP TABLE #Results
END
当从ASP.NET将SearchFlag设置为true时,我只想获取搜索的值@asp中的动态查询集,例如:

"where ProductType = " + Convert.ToInt32(recordType.persoRecord) + 
" and AccountNumber like '%" + SearchValue + "%'";
WHERE AccountNumber LIKE '%" + SearchValue + "%'"
或者有很多不同的情况

当我按上述方式运行此存储过程时,会出现一个异常:

将varchar值“select”转换为数据类型int时,转换失败


关于

要使存储过程使用动态where语句,最好使用sp_executesql

例如:

EXEC sp_executesql 
N'select * from Employees where Id = @param1', 
N'@param1 int'
,@param1 = 1
有关动态查询的更多信息,请参阅以下网站


注释太长,但您需要了解发生错误的原因以修复它。您的代码中有这个片段

select @SearchQuerySQL = 'SELECT ' + @RecordCount +
首先,如果您打算分配一个标量值,例如@SearchQuerySQL,那么您应该使用SET,而不是SELECT。这是你空闲时可以研究的另一个话题。下面的赋值表达式是要进行字符串连接的地方。不幸的是,加号运算符的解释因所涉及的数据类型而异

当数据库引擎遇到涉及2种不同数据类型的运算符时会发生什么情况。与任何其他语言一样,必须将一种或两种语言转换为相同的类型才能执行表示的操作。发动机是如何做到这一点的?这是有规则的。在这种情况下,int参数具有更高的优先级,因此该表达式中的字符串将转换为int。这将失败,并出现您遇到的错误

如果您想编写动态sql,您需要对tsql有深入的了解。在尝试重新发明车轮之前,你也应该首先考虑在因特网上搜索。也许Aaron的文章可能会有所帮助,但在这一点上可能对你有点帮助


当你在胡闹的时候,在过程声明中添加一些关于你打算支持的用法的注释。没有人应该阅读您的代码来理解它的功能和使用方法

这感觉像是一个XY问题,在表中存储WHERE子句是您永远不需要做的事情。这也为注射带来了一个大问题。上述内容也已经受到注入的严重影响,特别是select@SearchQuerySQL='select*from Results'+@DynamicQuery+'和…'等语句。有很多方法可以实现动态搜索条件,但并非所有方法都是好的。Erland Sommarskog对所有可以做到这一点的方法都有很好的解释,包括优点和缺点。作为一般规则,如果您要在客户端生成查询的任何逻辑,也就是说,不只是一个值列表,那么您几乎总是最好在客户端生成所有的查询,因为这样可以更诚实地了解注入风险,并且更容易在逃避方面进行实际管理和保护。但正如链接文章所解释的,您通常根本不需要动态SQL。感谢@SMor为您提供有用的文章和建议。我会考虑的。