Обновить поле с регулярным выражением (или аналогичным) - PullRequest
1 голос
/ 05 марта 2012

Итак, в моей таблице есть поле с именем Url, которое выглядит следующим образом: /MyServer/MyPage?Param=XXX.
Мне нужно запустить скрипт, чтобы обновить это поле с XXX, чтобы сказать YYY.У меня есть правила о том, что YYY соответствует тому, что XXX, дело в том, что я не знаю, как обновить ТОЛЬКО поля, параметр которых точно равен Param, и никаких других.

Такэто будут обновления:

/MyServer/MyPage?Param=XXX        ==>  /MyServer/MyPage?Param=XXX  
/MyServer/MyOtherPage?Param=AAA   ==>  /MyServer/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ  ==>  /MyServer/MyOtherPage?Param2=JJJ 
                                       (last row no changes since it is not param)

Я ясно дал понять?

Редактировать: У меня есть вспомогательная таблица с соответствием XXX YYY.Имейте в виду, XXX это только пример.На самом деле параметр является целым числом, поэтому длина значения параметра является переменной

Ответы [ 4 ]

2 голосов
/ 05 марта 2012

Это касается заботы Микаэля о том, что в URL могут появиться AAA, XXX и т. Д.Это также относится к случаю, когда параметр не является последним в URL.

DECLARE @URLs TABLE (URL VARCHAR(2000));

INSERT @URLs SELECT '/MyServer/MyPage?Param=XXX'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param=AAA'
   UNION ALL SELECT '/MyServerAAA/MyOtherPage?Param=AAA'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param2=JJJ'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param=AAA&Param2=JJJ'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param2=AAA&Param=AAA';

DECLARE @rules TABLE(pSrc VARCHAR(32), pDest VARCHAR(32));

INSERT @rules SELECT 'XXX', 'YYY'
    UNION ALL SELECT 'AAA', 'BBB'
    UNION ALL SELECT 'JJJ', 'KKK';

;WITH src AS
(
  SELECT URL, 
    pre = LEFT(URL, CHARINDEX('?', URL)-1), 
    post =  SUBSTRING(URL, CHARINDEX('?', URL), 2000)
  FROM @URLs
), sub AS
(
    SELECT src.URL, src.pre, src.post, r.pSrc, r.pDest, 
      i = PATINDEX('%[?&]Param=' + r.pSrc + '&%', post + '&')
    FROM src INNER JOIN @Rules AS r
    ON src.post + '&' LIKE '%[?&]Param=' + r.pSrc + '&%'
)
UPDATE u SET URL = pre + STUFF(post, i+7, LEN(pSrc), pDest)
FROM @URLs AS u INNER JOIN sub ON u.URL = sub.URL;

SELECT * FROM @URLs;

Результаты:

URL
--------------------------------
/MyServer/MyPage?Param=YYY
/MyServer/MyOtherPage?Param=BBB
/MyServerAAA/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ
/MyServer/MyOtherPage?Param=BBB&Param2=JJJ
/MyServer/MyOtherPage?Param2=AAA&Param=BBB

Добавление ссылок на документы для последующего вопроса.Да, STUFF - это функция.

STUFF (Transact-SQL): MSDN
PATINDEX (Transact-SQL): MSDN

1 голос
/ 05 марта 2012
declare @T table
(
  Col varchar(50)
)

insert into @T values
('/MyServer/MyPage?Param=XXX'),
('/MyServer/MyOtherPage?Param=AAA'),
('/MyServer/MyOtherPage?Param2=JJJ')

declare @P table
(
  ID int,
  P1 varchar(50),
  P2 varchar(50)
)

insert into @P values
(1, 'AAA', 'BBB'),
(2, 'XXX', 'YYY')

update T 
set Col = left(T.Col, len(T.Col)-len(P.P1))+P.P2
from @T as T
  inner join @P as P
    on right(T.Col, len(P.P1)+6) = 'Param='+P.P1
where P.ID = 1

select *
from @T

Результат:

Col
--------------------------------------------------
/MyServer/MyPage?Param=XXX
/MyServer/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ
0 голосов
/ 05 марта 2012

Просто для удовольствия, и поскольку в первоначальном вопросе упоминалось о RegEx, я подумал, что приведу пример, использующий регулярные выражения. Да, для этого требуется SQLCLR, и не каждый может или будет использовать это, но это вариант.

В этом примере используется существующая библиотека SQLCLR с именем SQL # (SQLsharp) , автором которой я являюсь, но функции регулярных выражений (только с 3 исключениями) бесплатны.

В примере используются примерные переменные URL-адресов и таблиц правил из ответа Аарона Бертранда, но в качестве исходных строк используются числа (так как это исходный запрос и регулярное выражение в этом отношении специфично), и я добавил тест -case, чтобы показать, что строка «222» не соответствует ни одной части «2222».

DECLARE @URLs TABLE (URL VARCHAR(2000));

INSERT @URLs SELECT '/MyServer/MyPage?Param=111'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param=222'
   UNION ALL SELECT '/MyServer222/MyOtherPage?Param=222'
   UNION ALL SELECT '/MyServer222/MyOtherPage?Param=2222'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param2=333'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param=222&Param2=333'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param=2222&Param2=333'
   UNION ALL SELECT '/MyServer/MyOtherPage?Param2=222&Param=222';

DECLARE @Rules TABLE(pSrc VARCHAR(32), pDest VARCHAR(32));

INSERT @Rules SELECT '111', 'YYY'
    UNION ALL SELECT '222', 'BBB'
    UNION ALL SELECT '2222', 'bbb'
    UNION ALL SELECT '333', 'KKK';


SELECT SQL#.RegEx_Replace(u.url,
            '(.*Param=)' + r.pSrc + '([^0-9]+|$)',
            '$1' + r.pDest + '$2',
            -1, 1, '')
FROM @URLs u
CROSS JOIN @Rules r
WHERE SQL#.RegEx_IsMatch(u.url,
            '(.*Param=)' + r.pSrc + '([^0-9]+|$)',
            1, '') = 1

-- OR, using RegEx look-behind and look-ahead
SELECT SQL#.RegEx_Replace(u.url,
            '(?<=Param=)' + r.pSrc + '(?=[^0-9]+|$)',
            r.pDest,
            -1, 1, '')
FROM @URLs u
CROSS JOIN @Rules r
WHERE SQL#.RegEx_IsMatch(u.url,
            '(?<=Param=)' + r.pSrc + '(?=[^0-9]+|$)',
            1, '') = 1

Результаты:

/MyServer/MyPage?Param=YYY
/MyServer/MyOtherPage?Param=BBB
/MyServer222/MyOtherPage?Param=BBB
/MyServer222/MyOtherPage?Param=bbb
/MyServer/MyOtherPage?Param=BBB&Param2=333
/MyServer/MyOtherPage?Param=bbb&Param2=333
/MyServer/MyOtherPage?Param2=222&Param=BBB

Чтобы быть справедливым для строгих решений T-SQL, это было проверено не на производительность, а на функциональность и гибкость. Какое решение работает лучше, должно быть проверено на вашем сервере.

0 голосов
/ 05 марта 2012

Вот метод replace().

РЕДАКТИРОВАТЬ: добавлена ​​гибкость.

declare @myURLs table(url varchar(1000))
insert into @myURLs values ('/MyServer/MyPage?Param=XXX&Param2=JJJ'); --should update
insert into @myURLs values ('/MyServer/MyPage?Param2=XXX'); --should not update
insert into @myURLs values ('/MyServer/MyOtherPage?Param2=JJJ&Param=AAA'); --should update
insert into @myURLs values ('/MyServer/MyOtherPage?Param=AAAA'); --should not update
insert into @myURLs values ('/MyServer/MyOtherPage?Param=AAAA&Param2=JJJ'); --should not update

declare @replacements table(targetStr varchar(80), replStr varchar(80));
insert into @replacements values ('Param=AAA','Param=BBB');
insert into @replacements values ('Param=XXX','Param=YYY');

-- ANSI-92 syntax
update u
set url=REPLACE(url,r.targetStr,r.replStr)
from @myURLs u
inner join @replacements r on 
    (PATINDEX('%[?&]'+r.targetStr,url)>0
    or PATINDEX('%[?&]'+r.targetStr+'[?&]%',url) > 0);  

SELECT * 
FROM @myURLs;

Результат:

url
------------------------------------------------
/MyServer/MyPage?Param=YYY&Param2=JJJ
/MyServer/MyPage?Param2=XXX
/MyServer/MyOtherPage?Param2=JJJ&Param=BBB
/MyServer/MyOtherPage?Param=AAAA
/MyServer/MyOtherPage?Param=AAAA&Param2=JJJ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...