Генерация динамического оператора PATINDEX - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть следующие две строки:

DECLARE @Str1 VARCHAR(MAX) = 'John A Mak|Street Road UAE'
DECLARE @Str2 VARCHAR(MAX) = '[First Name],[Last Name],[Middle Name]|[Address1],[Address2]'

Примечание. Обе строки являются динамическими и могут иметь более или менее значения.

Ожидаемый результат: Требуется ли какой-либо из заданного текстаприсутствует в данных столбцах с помощью PATINDEX.Следующий оператор PATINDEX будет использоваться в предложении WHERE оператора SELECT.

PATINDEX('John',[First Name]) + PATINDEX('A',[First Name]) + PATINDEX('Mak',[First Name]) + 
PATINDEX('John',[Last Name]) + PATINDEX('A',[Last Name]) + PATINDEX('Mak',[Last Name]) +
PATINDEX('John',[Middle Name]) + PATINDEX('A',[Middle Name]) + PATINDEX('Mak',[Middle Name]) +
PATINDEX('Street',[Address1]) + PATINDEX('Road',[Address1]) + PATINDEX('UAE',[Address1]) +
PATINDEX('Street',[Address2]) + PATINDEX('Road',[Address2]) + PATINDEX('UAE',[Address2]) > 0

Моя попытка:

DECLARE @Str1 VARCHAR(MAX) = 'John A Mak|Street Road UAE'
DECLARE @Str2 VARCHAR(MAX) = '[First Name],[Last Name],[Middle Name]|[Address1],[Address2]'
DECLARE @Length int = 0
DECLARE @Length1 int = 0
DECLARE @Length2 int = 0
DECLARE @Position int = 0
DECLARE @Position1 int = 0
DECLARE @Position2 int = 0
DECLARE @Value varchar(max)
DECLARE @Value1 varchar(max)
DECLARE @Value2 varchar(max)
DECLARE @P_Str2 VARCHAR(MAX) = ''
DECLARE @P_Str3 VARCHAR(MAX) = ''
DECLARE @P_Str1 VARCHAR(MAX) = ''
DECLARE @FinalString VARCHAR(MAX) = ''

SET @P_Str1 = @Str1+'|';
SET @P_Str3 = @Str2+'|';

IF OBJECT_ID('tempdb..#tempt', 'U') IS NOT NULL DROP TABLE #tempt;
CREATE TABLE #tempt(keywords varchar(max));


WHILE CHARINDEX('|', @P_Str3, @Position2+1)>0
BEGIN
    set @Length2 = CHARINDEX('|', @P_Str3, @Position2+1) - @Position2
    set @Value2 = SUBSTRING(@P_Str3, @Position2, @Length2)

    SET @P_Str2 = @Value2+',';

    PRINT('--'+@P_Str2);
    --WHILE LOOP for creating string for PAT INDEX
    WHILE CHARINDEX(',', @P_Str2, @Position+1)>0 
    BEGIN
        set @Length = CHARINDEX(',', @P_Str2, @Position+1) - @Position
        set @Value = SUBSTRING(@P_Str2, @Position, @Length)

        WHILE CHARINDEX('|', @P_Str1, @Position1+1)>0
        BEGIN
            set @Length1 = CHARINDEX('|', @P_Str1, @Position1+1) - @Position1
            set @Value1 = SUBSTRING(@P_Str1, @Position1, @Length1)  

            PRINT('Value1--'+@Value1);
            PRINT('Value--'+@Value);
            INSERT INTO #tempt 
                SELECT DISTINCT split.a.value('.', 'VARCHAR(100)') AS Keywords
                FROM
                (
                    SELECT CAST ('<S>' + REPLACE(ltrim(rtrim(@Value1)), ' ', '</S><S>') + '</S>' AS XML) AS Element 
                ) AS a
                CROSS APPLY Element.nodes ('/S') AS split(a)
                WHERE split.a.value('.', 'VARCHAR(100)') <> ''; 

                SET @FinalString  += STUFF(( SELECT '(PATINDEX('''+keywords+''','+@Value+'),''''0'''') + '
                                             FROM #tempt FOR XML PATH('')), 1,0, '');   

                DELETE FROM #tempt;

            SET @Position1 = CHARINDEX('|', @P_Str1, @Position1+@Length1) +1
        END

        SET @Position = CHARINDEX(',', @P_Str2, @Position+@Length) +1

    END 

    SET @Position2 = CHARINDEX('|', @P_Str3, @Position2+@Length2) +1

END 
PRINT(@FinalString);

Но не удается получить ожидаемый результат.

1 Ответ

0 голосов
/ 01 декабря 2018

Это не очень динамический SQL, однако ...

USE Sandbox;
DECLARE @Str1 VARCHAR(MAX) = 'John A Mak|Street Road UAE';
DECLARE @Str2 VARCHAR(MAX) = '[First Name],[Last Name],[Middle Name]|[Address1],[Address2]';

DECLARE @WHERE nvarchar(MAX);
SET @WHERE = STUFF((SELECT N' + ' + NCHAR(10) + 
                         STUFF((SELECT N' + ' +NCHAR(10)+
                                       N'PATINDEX(' + QUOTENAME(DSn.Item,'''') + N',' + DSc.Item + N')' --This trusts no injection.I don't like this.
                                FROM dbo.DelimitedSplit8K(DS1.Item,' ') DSn
                                     CROSS APPLY dbo.DelimitedSplit8K(DS2.Item,',') DSc
                                ORDER BY DSc.ItemNumber, DSn.ItemNumber
                                FOR XML PATH(N'')),1,4,N'')
                  FROM dbo.DelimitedSplit8K (@Str1,'|') DS1
                       CROSS APPLY dbo.DelimitedSplit8K (@Str2,'|') DS2
                  WHERE DS1.ItemNumber = DS2.ItemNumber
                  ORDER BY DS1.ItemNumber
                  FOR XML PATH(N'')),1,4,N'') + N' > 0'

SELECT @WHERE;

Это выводит:

PATINDEX('John',[First Name]) + 
PATINDEX('A',[First Name]) + 
PATINDEX('Mak',[First Name]) + 
PATINDEX('John',[Last Name]) + 
PATINDEX('A',[Last Name]) + 
PATINDEX('Mak',[Last Name]) + 
PATINDEX('John',[Middle Name]) + 
PATINDEX('A',[Middle Name]) + 
PATINDEX('Mak',[Middle Name]) + 
PATINDEX('Street',[Address1]) + 
PATINDEX('Road',[Address1]) + 
PATINDEX('UAE',[Address1]) + 
PATINDEX('Street',[Address2]) + 
PATINDEX('Road',[Address2]) + 
PATINDEX('UAE',[Address2]) > 0

Обратите внимание на использование DelimitedSplit8k, котороевам понадобится ваш экземпляр, чтобы сделать это.

Редактировать / Примечание: Это не безопасно для инъекций.Именно из-за + DSc.Item +.OP в своих выборочных данных предоставляет уже заключенные в кавычки строки;поэтому предполагается , что строки правильно заключены в кавычки;Т.е. не "[" & ColumnName & "]" (который все еще открыт для инъекции, так как любой пройденный ] не будет экранирован).Если имена столбцов не указаны должным образом в других местах, я настоятельно рекомендую снять скобки ([]) в переданном значении и использовать вместо него + QUOTENAME(DSc.Item) +.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...