我正在处理一个接受字符串并返回一个新文本字符串的存储过程。输入参数为@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能够提供帮助吗?
答案 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)
答案 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代码,那就更多了。通常在使用令牌时,我会努力重用代码,因为代码中的一部分可能会崩溃并且只会损害其中的一部分,而不是将整个代码整理下来。