2011-06-29 1 views
1

文字列入力に基づいて値を動的に計算するオプションを検討しています。たとえば、次の文字列入力を取ります。T-SQL構文解析ストリングとアクションの実行

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

数字32,35,12,34はIDの「プレースホルダ」です。私がしようとしていることは、以下の通りです。 ID 32でメトリックを取得し、値を返す関数をいくつか適用します。次に、メトリックID 35に適用された同じ関数によって戻された値にその値を追加します。

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

単純な加算文字列から始めるほうが簡単で、他の演算子( - 、/、*)を使うのが簡単です。

これはtsqlで可能ですか?正規表現オプション(正規表現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

私はこの解決策も好きです。変数名でも簡単に従うことができます。いい物。小数点はありません...整数はDBテーブルのID列を表します。 – thomas