更新存储在表中的UDF名称以添加参数值

时间:2018-01-25 08:17:18

标签: sql sql-server sql-server-2012 sql-update

我有数千个UDF名称存储在表中,并在需要的地方动态执行。问题是我在函数unit中添加了一个新参数dbo.GetStockPrice(6544,1)所以我需要再发送一个参数值1 bue它可以是任意数据,数据应该更改为对于dbo.GetStockPrice(6544,1,1)存在的所有行,dbo.GetStockPrice。所以我正在寻求查询一次更新这些。

样本数据

DECLARE @table AS TABLE(id INT, UDF VARCHAR(1000))
INSERT INTO @table VALUES
(7774,'dbo.GetStockPrice(1211,1)*dbo.GetStockPrice(1211,1)'),
(7775,'dbo.GetStockPrice(232,1)'),
(7778,'dbo.GetStockPrice(6456,1)'),
(7780,'dbo.GetStockPrice(34,1)'),
(7784,'dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1)+1)'),
(7786,'dbo.GetStockPrice(9876,1)'),
(7906,'dbo.GetStockPrice(5565,1)'),
(7911,'dbo.GetStockPrice(7886,1)'),
(7912,'dbo.GetStockPrice(87,1)'),
(8403,'dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1)+dbo.FNAMargin(1,NULL,0)')

预期产出:

7774    dbo.GetStockPrice(1211,1,1)*dbo.GetStockPrice(1211,1,1)
7775    dbo.GetStockPrice(232,1,1)
so on......

我仍在尝试REPLACESUBSTRING,但无法提出任何解决方案。在行中遇到不同长度和位置的困难。

寻求帮助!!提前谢谢你:)

1 个答案:

答案 0 :(得分:0)

尝试这种方法:

DECLARE @table AS TABLE(id INT, UDF VARCHAR(1000))
INSERT INTO @table VALUES
(7774,'dbo.GetStockPrice(1211,1)*dbo.GetStockPrice(1211,1)'),
(7775,'dbo.GetStockPrice(232,1)'),
(7778,'dbo.GetStockPrice(6456,1)'),
(7780,'dbo.GetStockPrice(34,1)'),
(7784,'dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1)+1)'),
(7786,'dbo.GetStockPrice(9876,1)'),
(7906,'dbo.GetStockPrice(5565,1)'),
(7911,'dbo.GetStockPrice(7886,1)'),
(7912,'dbo.GetStockPrice(87,1)'),
(7913,'dbo.Blah(87,1)'),
(8403,'dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1)+dbo.FNAMargin(1,NULL,0)');

- 查询

WITH SplitToParts AS
(
    SELECT t.*
          ,A.parted
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PartNr
          ,B.part.value('text()[1]','nvarchar(max)') AS Part
    FROM @table AS t
    CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT t.UDF AS [*] FOR XML PATH('')),'dbo.GetStockPrice(','</x><x>$$$FoundIt$$$</x><x>') + '</x>' AS XML)) AS A(parted)
    CROSS APPLY parted.nodes(N'/x') AS B(part)
    WHERE UDF LIKE '%dbo.GetStockPrice(%'
)
,modified AS
(
    SELECT *
          ,CASE WHEN LAG(stp.Part) OVER(PARTITION BY id ORDER BY PartNr)='$$$FoundIt$$$' THEN STUFF(stp.Part,CHARINDEX(')',stp.Part),0,',1') ELSE stp.Part END AS Added
    FROM SplitToParts AS stp
)
SELECT t2.*
      ,(
        SELECT REPLACE(m.added,'$$$FoundIt$$$','dbo.GetStockPrice(')
        FROM modified AS m 
        WHERE m.id=t2.id 
        ORDER BY m.PartNr
        FOR XML PATH(''),TYPE
       ).value('.','nvarchar(max)')
FROM @table AS t2
WHERE UDF LIKE '%dbo.GetStockPrice(%';

结果

7774    dbo.GetStockPrice(1211,1,1)*dbo.GetStockPrice(1211,1,1)
7775    dbo.GetStockPrice(232,1,1)
7778    dbo.GetStockPrice(6456,1,1)
7780    dbo.GetStockPrice(34,1,1)
7784    dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1,1)+1)
7786    dbo.GetStockPrice(9876,1,1)
7906    dbo.GetStockPrice(5565,1,1)
7911    dbo.GetStockPrice(7886,1,1)
7912    dbo.GetStockPrice(87,1,1)
8403    dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1,1)+dbo.FNAMargin(1,NULL,0)

一些解释:使用您的函数名称作为拆分器,将对字符串进行部分剪切。很高兴您使用[sql-server-2012]对此进行了标记,因此您可以使用LAG()。这将测试前一个元素,如果它是$$$FoundIt$$$。在这种情况下,第一个右括号将获得额外的,1。其余的是协调。

注意:如果您的呼叫可能包含计算值,例如

dbo.GetStockPrice(1211,(1+2))
or
dbo.GetStockPrice(dbo.SomeOtherFunc(1),1)

... 第一个右括号是插入,1的错误位置。但这会变得非常棘手......你必须通过它来运行它,通过char来计算char,并计算左括号以找到相关的结束。