用于替换字符串中的某些变量的存储过程

时间:2013-04-05 16:55:00

标签: sql-server-2008 tsql

我正在处理一个接受字符串并返回一个新文本字符串的存储过程。输入参数为@OrderId@OrderText,这是一个带有美元符号的字符串,包含变量,如此... $Order Name$ sent to $Customer$

有效变量位于Variables表中(诸如Order Name,Customer之类的值,其中总共25个应保持相当静态)。变量只能在字符串中使用一次。

存储过程需要返回字符串,但变量将替换为各自的值。

示例1

输入:123, $Order Name$ sent to $Customer$

返回:Toolkit sent to StackCustomer Inc.

例2

输入:456, $Customer$ requests $delivery method$ for $order type$

返回:ABC Inc requests fast shipping for pallet orders.

可以使用函数检索每个变量。

    DECLARE @OrderId int = 123
    DECLARE @InputText VARCHAR(500) = '$Order Name$ sent to $Customer$'
    select 
     @InputText = case when @InputText like '%$order name$%' 
             then replace(@InputText, '$Order Name$', getOrderName(id) else '' end,
     @InputText = case when @InputText like '%$customer$' 
             then replace(@InputText, '$Customer$', getCustomer(id) else '' end
      -- repeat 25 times

有更好的方法吗?我主要担心的是可维护性 - 如果添加,重命名或删除变量,则需要更改此存储过程(尽管我被告知每年只会发生几次,如果这样)。在这种情况下,动态sql能够提供帮助吗?

2 个答案:

答案 0 :(得分:3)

就个人而言,我会创建一个关键字表来维护它。像这样的东西

CREATE TABLE [keywords] (
  key_value VARCHAR(100) NOT NULL,
  function_value VARCHAR(100) NOT NULL
  )
INSERT INTO [keywords]
VALUES
('$Customer$','getCustomer(id)'),
('$Order Name$' ,'getOrderName(id)'),
('$order type$','getOrderType(id)')

然后使用动态sql创建REPLACE SQL

DECLARE @OrderId int = 123
DECLARE @InputText VARCHAR(500) = '$Order Name$ sent to $Customer$'

DECLARE @sql VARCHAR(8000) = 'SELECT '

SELECT 
  @sql = @sql + 
  ' @InputText = replace(@InputText, ''' + key_value + ''', ' + function_value + ')'
    + ' ,'
FROM keywords
WHERE  @InputText LIKE '%' + key_value + '%'


SELECT @sql = LEFT(@sql, LEN(@sql) -1)
PRINT @sql

EXEC(@sql)

SQLFiddle

答案 1 :(得分:0)

如果您要为该过程使用输入变量,我真的不明白为什么需要进行标记化。

SQL Management Studio已经有以下形式提供的令牌模板:

<(tokenName),(datatype),(defaultvalue)>

您可以使用带有CTRL + SHIFT + M或ALT&gt;的SQL Managment Studio直接填充数据。 Q> S在2012年,或通过文本在环境中查找其值。

如果你试图输入一个外部开发平台访问的输入,这个平台改变了像C#/ VB.NET中的ADO.NET或实体框架之类的字符串,我仍然无法理解为什么你不会只是做更多输入变量。

你可以很容易地做到这一点:

Declare @OrderPlace varchar(128), @Customer varchar(64), @StringCombine varchar(512);

Select 
   @OrderPlace = 'Place I am at'
,  @Customer = 'Mr Customer';

Select @StringCombine = @Customer + ' order at ' + @OrderPlace

然后,如果另一种语言访问了您的SQL服务器过程,则只需要输入两个参数@Customer和@OrderPlace。您甚至可以将@StringCombine设置为输出变量。这比文本替换字符然后运行字符串要好得多。这可能会导致SQL注入攻击,因此输入输入是返回数据的重要部分,特别是如果要在运行之前更改SQL运行的内容。

你提到了可维护性,这更加健壮,因为如果我将逻辑更改为proc但是不要更改变量名称,我不必更改任何其他内容。如果我必须更改ADO.NET或其他库以获取引用,然后更改SQL代码,那就更多了。通常在使用令牌时,我会努力重用代码,因为代码中的一部分可能会崩溃并且只会损害其中的一部分,而不是将整个代码整理下来。