我在MS SQL Server中创建一个函数,它允许报表开发人员从用户输入字段中获取数据并将其转换为可行的数据格式。 99%的时间,我在下面使用的代码都可以使用。但是,用户永远不会想出一些方法来不可能搞砸他们应该输入的数据(我为一家拥有数千名入门级数据录入员工的大公司工作)。
我主要挣扎的是转变非常糟糕的用户输入,例如$ 1,00,000..411'成为可行的DECIMAL格式。我希望它变成' 100000.41' (因为那是我们最接近知道用户输入时的内容),但我在下面使用的代码是只会把它变成' 100000..411'。
这是我迄今为止编写的代码。它允许报表开发人员选择他或她想要返回的数据类型,并允许传递自定义正则表达式:
CREATE FUNCTION dbo.udf_FieldSanitizer
(
@String VARCHAR(250)
,@Datatype VARCHAR(250)
)
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE @Expression VARCHAR(10)
SELECT
@Expression = CASE
WHEN @Datatype = '1' THEN '^0-9-'
WHEN @Datatype = '2' THEN '^0-9.-'
WHEN @Datatype = '3' THEN '^a-z'
WHEN @Datatype = '4' THEN '^a-z '
WHEN @Datatype = '5' THEN '^a-z ,'
WHEN @Datatype = '6' THEN '^a-z0-9'
WHEN @Datatype = '7' THEN '^a-z0-9 '
WHEN @Datatype = '8' THEN '^a-z0-9 ,'
ELSE @Datatype
END
WHILE PATINDEX('%['+@Expression+']%',@String) > 0
SET @String = STUFF(@String,PATINDEX('%['+@Expression+']%',@String),1,'')
RETURN @String
END
答案 0 :(得分:1)
好吧,为了简单回答你的问题并坚持你想要的方式,我建议你在做SELECT之前添加一个检查并替换@String,如下所示:
DECLARE @Expression VARCHAR(10)
IF @Datatype = '2'
AND (SELECT LEN(@String) - LEN(REPLACE(@String,'.',''))) > 1
SET @String = REPLACE(@String,'..','.')
SELECT
@Expression = CASE
另外,您的@Datatype定义为VARCHAR(150),但您似乎正在使用数字。如果是这样,我会将其改为SMALLINT或TINYINT,但这是一篇不同的文章(以及你通常应该如何避免标量函数)。
此外,只要您必须处理自由文本,您将不断添加这些类型的错误处理子句(用户将找到解决问题的独特方法),这就是为什么它最好留在UI级别正如FLICKER所建议的那样。