SQL Серверная хранимая процедура Dynami c Где условие во временной таблице - PullRequest
0 голосов
/ 14 января 2020

Я использую ASP. NET и серверную базу данных SQL.

У меня есть варианты поиска значений из таблицы gridview по некоторым критериям. Критерии в основном независимы друг от друга.

Например:

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

или

"where fileid=" + File_ID + ShowSearch + 
" and lower(j.CardHolderName) like '%" + SearchValue.Trim().ToLower() + "%'

Существует множество вариантов поиска пользователем. У меня есть миллионы строк данных в этой таблице, чтобы извлечь данные и быстро связать их с 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

Если для SearchFlag установлено значение true из ASP. NET, я хочу получить только искомое значение. @DynamicQuery устанавливается из asp, например:

WHERE AccountNumber LIKE '%" + SearchValue + "%'"

или со многими другими случаями.

Когда я запускаю эту хранимую процедуру, как описано выше, я получаю исключение:

Преобразование не удалось при преобразовании значения varchar 'select' в тип данных int

Regards

Ответы [ 2 ]

0 голосов
/ 14 января 2020

Слишком долго для комментария, но вам нужно понять, почему возникает ошибка, чтобы ее исправить. У вас есть этот фрагмент в вашем коде

select @SearchQuerySQL = 'SELECT ' + @RecordCount +

Во-первых, если вы намереваетесь присвоить скалярное значение (например, @ SearchQuery SQL), вам следует использовать SET, а не SELECT. Это еще одна тема, которую вы можете исследовать на досуге. Следующее выражение присваивания - это место, где вы намеревались выполнить конкатенацию строк. К сожалению, интерпретация оператора со знаком плюс меняется в зависимости от используемых типов данных.

Что происходит, когда ядро ​​базы данных встречает оператора, который включает в себя 2 разных типа данных. Как и любой другой язык, один (или оба) должны быть преобразованы в один и тот же тип для выполнения указанной операции. Как двигатель делает это? Существуют правила для приоритет типа данных . В этом случае ваш параметр int имеет более высокий приоритет, и поэтому эти строки в этом выражении преобразуются в int. Это не с ошибкой, с которой вы столкнулись.

Если вы хотите написать Dynami c sql, вам необходимо иметь глубокое понимание t sql. Вы также должны рассмотреть поиск inte rnet, прежде чем пытаться заново изобрести колесо. Может быть, статья Аарона о dynamici c pagination могла бы помочь - но это может быть немного для вас в данный момент.

И пока вы разбираетесь с вещами, добавьте несколько комментариев в декларации процедуры об использовании, которое вы намереваетесь поддерживать. Никто не должен читать ваш код, чтобы понять, что он делает и как его использовать.

0 голосов
/ 14 января 2020

Чтобы сделать хранимую процедуру, используйте ваш динамический оператор c, где лучше использовать sp_executesql

пример:

EXEC sp_executesql 
N'select * from Employees where Id = @param1', 
N'@param1 int'
,@param1 = 1

для получения дополнительной информации о динамическом c запрос см. на следующем сайте

SQL Сервер Dynami c SQL

...