2011-06-29 2 views
1

Я изучаю параметры для динамического вычисления значений на основе ввода строки. Возьмем, например, следующий ввод строки.T-SQL Parse String и выполнять действия

"(32+35)/(12+34)" 

Номера 32, 35, 12 и 34 являются «заполнителями» для идентификаторов. В разговорной речи я пытаюсь сделать следующее. Возьмите метрику с идентификатором 32 и примените к ней некоторую функцию, которая возвращает значение. Затем добавьте это значение к значению, возвращенному той же функцией, примененной к метрику id 35, и так далее и т. Д.

(dbo.foo(32) + dbo.foo(35))/(dbo.foo(12) + dbo.foo(34)) 

Возможно, было бы проще начать с простой строки добавления и работать с другими операторами (-, /, *).

Возможно ли это в tsql? Открытые для регулярных выражений (имеют функцию regex tsql) и все, что вы можете придумать.

Возможно, замените регулярное выражение на целые числа, чтобы вставить имя функции в строку, и затем exec() строку, чтобы получить результат?

Давайте не будем обсуждать плюсы и минусы такого метода ... Я знаю, что это не истинное решение «базы данных» для моей проблемы, но вы хотите изучить его больше.

+0

Возможно, вы не получите много полезных ответов, так как вы в основном говорите «Я знаю, что это плохое решение, но вы хотите сделать это в любом случае». Я могу задать вопрос о automotive.se о лучшем способе смазки моего двигателя песком, но это не значит, что я не должен ожидать, что его исправят. ** Удачи! ** – JNK

+0

JNK, вы, безусловно, правы. Однако я никогда не говорил, что думаю, что это плохое решение, а не «настоящая база данных». Определенные ситуации требуют разных решений и без полной справки по моей проблеме. Я не думаю, что вы можете судить о одном решении над другим. – thomas

+1

Несомненно, мы можем судить об этом. Суждение может быть неточным без знания специфики вашей ситуации, но огромный опыт многих людей здесь приводит меня к мысли, что если у них есть проблемы даже без скрытых особенностей, что вы, вероятно, будете в неправильном направлении. Я также добавлю, что почти все думают, что их ситуация достаточно уникальна, чтобы оправдать обычную мудрость. По моему опыту большинство из них ошибаются. –

ответ

2

Я смог заставить это работать как доказательство концепции с использованием опции регулярного выражения, о которой я упоминал.

declare @str as nvarchar(1000) 
    declare @regex as nvarchar(1000) 

    set @str = '(32+33)/(12+93)' 
    set @regex = 'select ' + dbo.regex_replace('\d+','dbo.foo($&)', @str, 1, 0) 

    exec(@regex) 

Моя функция regex_replace принимает параметры (@pattern, @replacement, @subject, @global, @multiline). Я нашел эту функцию через google. Если вы ищете, это «RegexReplace», я верю.

Этот код предоставляет ответ, который я ищу.

1

RegEx довольно изящный. Но отчасти потому, что не у всех есть RegEx, и отчасти потому, что я уже выполнил всю работу, вот прямое решение T-SQL (не самые надежные и ужасные имена переменных, но он выполняет свою работу). Обратите внимание, что он принимает целые числа - если вы ставите десятичные числа там, вам придется также проверить их.

DECLARE 
    @foo NVARCHAR(MAX) = N'(32+35)/(12+34)', 
    @bar NVARCHAR(MAX) = N''; 

DECLARE 
    @i INT = 0, 
    @z INT = LEN(@foo), 
    @y INT, 
    @s NVARCHAR(12), 
    @s2 NVARCHAR(12); 

WHILE @i <= @z 
BEGIN 
    SET @s = SUBSTRING(@foo, @i, 1); 
    IF ASCII(@s) BETWEEN 48 AND 57 
    BEGIN 
     SET @bar += 'dbo.foo('; 
     SET @y = @i + 1; 
     WHILE @y <= @z 
     BEGIN 
      SET @s2 = SUBSTRING(@foo, @y, 1); 
      IF ASCII(@s2) BETWEEN 48 AND 57 
      BEGIN 
       SET @s += @s2; 
       SET @y += 1; 
      END 
      ELSE 
      BEGIN 
       BREAK 
      END 
     END 
     SET @s += ')'; 
     SET @i = @y - 1; 
    END 
    SET @bar += @s; 
    SET @i += 1; 
END 

PRINT @bar; 

--EXEC('SELECT ' + @bar); 
+0

Мне тоже нравится это решение. Достаточно легко следовать даже с именами переменных. Хорошая вещь. Нет десятичных знаков ... целые числа будут представлять собой столбец идентификатора в таблице БД. – thomas