Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Парсинг параметров в запросе  [new]
SrcGuest
Guest
Есть поле в таблице, хранящее значения SQL-шаблонов
declare @s varchar(max)
set @s = 'select top 10 <%p_lookup_field%>   
from <%p_ref_table%>  
where <%p_code_field%> = <%p_code_value%>';

Как вытащить отсюда названия параметров вида <%ParamName%>?

Мои варианты:
1) Использовать RegExp, подключенные через OLE.
2) Написать последовательный разбор <%, %>

Какие еще есть варианты?
6 апр 12, 11:22    [12374714]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Glory
Member

Откуда:
Сообщений: 104751
Токенов же конечное число ?
Зачем их тогда парсить, если можно заменять прямыми replace-ми ?
6 апр 12, 11:24    [12374733]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Glory,

Да, конечное число. Хотелось автоматизировать процесс. Т.е. речь идет о создании таблицы, содержащей названия параметров шаблона. При создании шаблона на клиенте можно распарсить текст и определить какие параметры в нем содержаться. Этого сделано не было, но можно сделать сейчас.
Уже созданные шаблоны не имеют созданных параметров, поэтому нужно пройтись по всем шаблонам и проанализировать. Можно сделать это отдельно. С другой стороны при выполнении шаблона можно проанализировать, все ли параметры указаны, для этого нужно еще раз распарсить текст шаблона.

Выбирая между парсингом на клиенте или сервере склоняюсь к серверу. Осталось найти наиболее подходящий метод, чем и занимаюсь.
6 апр 12, 11:40    [12374831]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Glory
Member

Откуда:
Сообщений: 104751
Так вот для приведенного примера вы что хотите получить на выходе то ?
6 апр 12, 11:42    [12374848]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Glory,

Что-то типа
declare @s varchar(max)
set @s = 'select top 10 <%p_lookup_field%>   from <%p_ref_table%>  where <%p_code_field%> = <%p_code_value%>';

select *
from
	master.dbo.fnRegExp_Execute(@s, '<%\w{1,}%>', 1, 1) free1


Результат
Index	Position	Length	Value	SubIndex	SubValue
0 14 18 <%p_lookup_field%> NULL NULL
1 40 15 <%p_ref_table%> NULL NULL
2 63 16 <%p_code_field%> NULL NULL
3 82 16 <%p_code_value%> NULL NULL
6 апр 12, 11:44    [12374857]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
SrcGuest, пишете clr функцию для использования regexp, парсите шаблоны. если неохота парсить каждый раз, то результатами заполняете вспомогательную таблицу, например
6 апр 12, 12:06    [12375033]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Shakill,

Не вижу принципиального отличия от RegExp через OLE, как я привел выше. Да и не хочется студию ставить.
6 апр 12, 12:14    [12375099]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
SrcGuest,

пишут что парсинг через clr вариант будет быстрее чем через ole
http://social.msdn.microsoft.com/Forums/en/transactsql/thread/236fc312-5607-462f-9a61-f77c869298ef
не принципиально, но в примере разница по времени существенная, кому-то это может оказаться важно
6 апр 12, 12:22    [12375179]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
Не вижу принципиального отличия от RegExp через OLE
Вообщето я нарывался на разные по уровню глюки и побочные эффекты. К примуру OLE выпадал, какжись на CROSS APPLY.

SrcGuest
пишут что парсинг через clr ...
Надеюст утечки памяти пофиксены.
6 апр 12, 12:57    [12375512]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
через clr
Да и вообще, эта ма-а-а-ленькая прокладка между SQL и вызовом библиотечного RegEx эпична.
6 апр 12, 13:03    [12375544]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Mnior
SrcGuest
через clr
Да и вообще, эта ма-а-а-ленькая прокладка между SQL и вызовом библиотечного RegEx эпична.
есть варианты лучше? :)
6 апр 12, 13:07    [12375582]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Реализовал простой отбор
if object_id('dbo.[ff_parseparams]') is not null
    drop function dbo.[ff_parseparams]
go
create function [dbo].[ff_parseparams]
(
	@p_sql_text varchar(max)
)
returns @params table (
            [index] int not null
           ,param_name varchar(128) not null
           ,pos_start int
           ,pos_end int
           ,param_entries int
        )
as
begin
    declare @len          int
           ,@pos          int
           ,@buf2         varchar(2)
           ,@buf1         varchar(1)
           ,@flag_expr    bit
           ,@startpos     int
           ,@endpos       int
           ,@param        varchar(128)
           ,@param_index  int
    
    
    set @len = len(@p_sql_text);
    
    set @pos = 0
    set @flag_expr = 0
    set @param_index = 0
    
    while @pos<@len- 1
    begin
        set @pos = @pos+1
        set @buf2 = substring(@p_sql_text ,@pos ,2);
        set @buf1 = left(@buf2 ,1);		
        
        if @buf2='<%'
        begin
            set @startpos = @pos;	
            set @flag_expr = 1;
        end
        else 
        if @buf2='%>'
        begin
            if @flag_expr=1
            begin
                set @endpos = @pos;
                set @flag_expr = 0;
                set @param = substring(@p_sql_text ,@startpos ,@endpos- @startpos+2);
                
                if not exists (
                       select *
                       from   @params p
                       where  lower(p.param_name) = lower(@param)
                   )
                    insert @params
                      (
                        [index]
                       ,param_name
                       ,pos_start
                       ,pos_end
                       ,param_entries
                      )
                    values
                      (
                        @param_index
                       ,@param
                       ,@startpos
                       ,@endpos
                       ,1
                      )
                else
                    update @params
                    set    param_entries = param_entries+1
                    where  lower(param_name) = lower(@param)
                
                set @param_index = @param_index+1;
            end
        end;
        
        if @buf1=' '
           and @flag_expr=1
            set @flag_expr = 0;
    end
    
    return
end;
go

Тест
select *
from   ff_parseparams(
           'select 1 from <%tbl%> where <%p_par%> and <% das%> = ''<%p_val %> and <%daad%>%> = <%p_par%>'
       )

Параметры не должны содержать пробелов в названии
6 апр 12, 13:58    [12376088]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
aleks2
Guest
Долго мучился?

ALTER function [dbo].[f_StrToTableEx](@str varchar(8000), @delimiter varchar(64)=',')
returns table as
return(
WITH str_nums ( n1, n2, Number ) 
AS 
( 
select  1-DATALENGTH(@delimiter) as n1, charindex(@delimiter, @str+@delimiter) as n2, 0 as Number  
UNION ALL 
select n2 as n1, charindex(@delimiter, @str+@delimiter, n2+DATALENGTH(@delimiter)) as n2, Number+1 as Number
from str_nums
WHERE n2<DATALENGTH(@str)
) 
SELECT SUBSTRING(@str, n1+DATALENGTH(@delimiter), n2-n1-DATALENGTH(@delimiter)) as Value, Number, n1+DATALENGTH(@delimiter) as StartPosition FROM str_nums
)
go

declare @s varchar(1024)

set @s='select 1 from <%tbl%> where <%p_par%> and <% das%> = ''<%p_val %> and <%daad%>%> = <%p_par%>'

select * 
from [dbo].[f_StrToTableEx](REPLACE(REPLACE(@s, '<%', ',%'), '%>', '%,'), ',')
WHERE LEFT(Value, 1)='%'
6 апр 12, 14:30    [12376376]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
aleks2,

Разные результаты
в моем случае
index	param_entry	param_name	pos_start	pos_end	param_entries
0 <%tbl%> tbl 15 20 1
1 <%p_par%> p_par 29 36 2
2 <% das%> das 43 49 1
3 <%daad%> daad 70 76 1

В твоем
Value	Number	StartPosition
%tbl% 1 16
%p_par% 3 30
% das% 5 44
%p_val % 7 56
%daad% 9 71
% 10 78
%p_par% 12 84
6 апр 12, 16:23    [12377424]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
Реализовал простой отбор
Тонко.

WHILE / IF - Перенесите топик в "ненормальное программирование"
6 апр 12, 16:35    [12377504]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
aleks2,

Разные результаты
в моем случае
indexparam_entryparam_namepos_startpos_endparam_entries
0<%tbl%>tbl15201
1<%p_par%>p_par29362
2<% das%> das43491
3<%daad%>daad70761


В твоем
ValueNumberStartPosition
%tbl%116
%p_par%330
% das%544
%p_val %756
%daad%971
%1078
%p_par%1284
Это не повод думать процедурно.
6 апр 12, 16:38    [12377517]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest, у вас кстати тоже ошибка.
CREATE FUNCTION [dbo].[fnTemplateParse] (
	 @Template	VarChar(max)
) RETURNS TABLE AS RETURN
WITH Parse (Pos,[Param],Rest) AS (
	SELECT	 Convert(BigInt,0)
		,Convert(SysName,NULL)
		,Convert(BigInt,0)
UNION ALL 
	SELECT	 P.Rest + F.Pos
		,Convert(SysName,SubString(@Template,P.Rest + F.Pos + 2,T.Pos - 2))
		,P.Rest + F.Pos + T.Pos
	FROM	Parse P	-- PatIndex не имееи StartPos :(
		CROSS APPLY(SELECT NullIf(PatIndex('%<[%]%',Stuff(@Template,1,P.Rest        ,'')),0)) F(Pos)
		CROSS APPLY(SELECT NullIf(PatIndex('%[%]>%',Stuff(@Template,1,P.Rest + F.Pos,'')),0)) T(Pos)
	WHERE	    F.Pos > 0
		AND T.Pos > 0
)	SELECT	 Pos
		,[Param]
	FROM	Parse
	WHERE	Pos > 0
GO
SELECT	*
FROM	dbo.fnTemplateParse('SELECT 1 FROM <%tbl%> WHERE <%p_par%> AND <% das%> = ''<%p_val %> AND <%daad%>%> = <%p_par%>')
ORDER BY Pos
PosParam
15tbl
29p_par
43 das
55p_val
70daad
83p_par
6 апр 12, 17:21    [12377741]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Mnior,

Нет ошибки. Я ввел атрибут param_entries в результирующий набор специально для того чтобы один и тот же параметр не попадал два раза в список. Вдобавок избавился от недопустимых символов в параметрах пробелов, апострофов и т.д. Но ваш код тоже проанализирую. Спасибо.
6 апр 12, 17:46    [12377897]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
Я ввел атрибут param_entries в результирующий набор специально для того чтобы один и тот же параметр не попадал два раза в список.
Хе. Модельная глупость.
1. Как это: есть Position и не показаны все вхождения параметров. Бессмыслица.
2. И что, тяжело Сгруппировать?!

Хотя, для императивистов это нормально, они не видят 99% вещей. Процедурномыслие не даёт мыслить категориями.
6 апр 12, 18:24    [12378114]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Mnior
SrcGuest
Я ввел атрибут param_entries в результирующий набор специально для того чтобы один и тот же параметр не попадал два раза в список.
Хе. Модельная глупость.
1. Как это: есть Position и не показаны все вхождения параметров. Бессмыслица.
2. И что, тяжело Сгруппировать?!

Да, действительно смысл выдавать все вхождения есть. Запрещать ввод некорректных названий тоже

Mnior
Хотя, для императивистов это нормально, они не видят 99% вещей. Процедурномыслие не даёт мыслить категориями.
Нарываюсь конечно, но что входит в 100% и в 99%? :)
6 апр 12, 18:32    [12378151]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
но что входит в 100% и в 99%?
А вам про группировку мало?
6 апр 12, 18:56    [12378241]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Mnior,

да, мало. Или вы считаете, что только выдача всех параметров без группировки - единственно верное решение, а остальные идиоты? :)
6 апр 12, 18:59    [12378255]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
Или вы считаете, что только выдача всех параметров без группировки
Мухаха. До вас не дошло.
Вы видимо и модульное программирование плохо понимаете.

Пишем нормальную функцию, логически полноценную. А далее пользуемся ей так, как нужно для данной задачи.
SELECT	[Param], Min(Pos), Count(*) -- ... 100500 других возможных подсчётов
FROM	dbo.fnTemplateParse('SELECT 1 FROM <%tbl%> WHERE <%p_par%> AND <% das%> = ''<%p_val %> AND <%daad%>%> = <%p_par%>')
GROUP BY [Param]
Придётся вам переосмыслить предыдущие посты.

Хотя возможно что нужно доразжевать по полочкам. Опять 3 листа расписывать. Опять много букав, опять ниасилили...
6 апр 12, 19:25    [12378347]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
SrcGuest
а остальные идиоты
Кстати неотъемлемый атрибут беседы. Это самооскорбления. Наполнение эмоциями разговор.
Естественно, эмоциональная окраска слов важнее чем смысл заложенный в них.
Более того, любое сказанное, это 100 пудовое утверждение, и типа никак не может быть предположением.
Траля-ля ещё 100500 атрибутов различий информационного метаболизма.

Ладно ладно, это я так в воздух, даже не не думайте, никаких личностей.
6 апр 12, 19:33    [12378381]     Ответить | Цитировать Сообщить модератору
 Re: Парсинг параметров в запросе  [new]
SrcGuest
Guest
Mnior
Ладно ладно, это я так в воздух, даже не не думайте, никаких личностей.

Нда, заклинило вас. Даже смайликов не видите :)
В топике уже озвучено 3 или 4 решения, выбирай на любой вкус, исходя из потребностей.
Боритесь со своей категоричностью (никаких личностей :) )
9 апр 12, 16:34    [12388834]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить