0

我在 SQL Server 2008 中有一个表,其中包含以文本形式存储的表达式的自定义验证条件,例如

StagingTableID    CustomValidation
----------------------------------
1                 LEN([mobile])<=30
3                 [Internal/External] IN ('Internal','External')
3                 ([Internal/External] <> 'Internal') OR (LEN([Contact Name])<=100)
...

我有兴趣确定表中的所有行是否都通过条件语句。为此,我正在编写一个验证存储过程,它检查给定表中给定字段中的所有值是否满足给定条件。SQL 不是我的强项,所以在阅读了这个问题之后,这是我第一次尝试解决这个问题:

EXEC sp_executesql N'SELECT @passed = 0 WHERE EXISTS (' +
                     N'SELECT * FROM (' +
                       N'SELECT CASE WHEN ' + @CustomValidationExpr + N' THEN 1 ' +
                       N'ELSE 0 END AS ConditionalTest ' +
                       N'FROM ' + @StagingTableName +
                     N')t ' +
                     N'WHERE t.ConditionalTest = 0)'
                  ,N'@passed BIT OUTPUT'
                  ,@passed = @PassedCustomValidation OUTPUT

但是,我不确定嵌套查询是否可以重写为一个,或者在这种情况下是否有更好的方法来测试所有行的有效性?

提前致谢!

4

3 回答 3

1

在我们回答最初的问题之前,您是否考虑过实施约束?这将首先防止不良数据进入您的数据库。还是这些必须在应用程序中动态设置?

ALTER TABLE StagingTable
    WITH CHECK ADD CONSTRAINT [StagingTable$MobileValidLength]
    CHECK (LEN([mobile])<=30)
GO

ALTER TABLE StagingTable
    WITH CHECK ADD CONSTRAINT [StagingTable$InternalExternalValid]
    CHECK ([Internal/External] IN ('Internal','External'))
GO

--etc...
于 2012-12-20T15:26:12.830 回答
1

您应该能够减少至少一个这样的子查询:

EXEC sp_executesql N'SELECT @passed = 0 WHERE EXISTS (' +
                       N'SELECT 1 FROM ' +  @StagingTableName +
                       N'WHERE NOT(' + @CustomValidationExpr + N')) ' +
                  ,N'@passed BIT OUTPUT'
                  ,@passed = @PassedcustomValidation OUTPUT
于 2012-12-20T15:28:37.517 回答
0

您需要将表达式连接在一起。我同意@PinnyM 的观点,即一个where子句更容易用于全表验证。但是,下一个问题将是如何识别哪些行未通过哪些测试。我会等你在回答之前问这个问题(作为一个单独的问题而不是作为对此问题的编辑提出)。

要创建where子句,如下所示:

declare @WhereClause nvarchar(max);
select @WhereClause = (select CustomValidation+' and '
                       from Validations v
                       for xml path ('')
                      ) + '1=1'

select @WhereClause = replace(replace(@WhereClause, '&lt;', '<'), '&gt;', '>'))

这种带有 和双选的奇怪结构for xml path('')是在 SQL Server 中连接值的最方便的方法。

此外,在执行 sp_executesql 调用之前将您的查询放在一起。它为您提供更多灵活性:

declare @sql nvarchar(max);
select @sql = '
select @passed = count(*)
from '+@StagingTableName+'
where '+@WhereClause

这是通过所有验证测试的数字。失败的where条款是:

declare @WhereClause nvarchar(max);
select @WhereClause = (select 'not '+CustomValidation+' or '
                       from Validations v
                       for xml path ('')
                      ) + '1=0'
于 2012-12-20T16:11:29.217 回答