我需要填充'Value'字段可能是'0'或'1'(false或true),具体取决于表达式。
以下是简单数据:
1 1 * 1 + 1 NULL
2 0 + 0 NULL
3 1 + 0 * 0 NULL
4 0 * 1 NULL
5 0 * 1 * 1 NULL
'Expression'字段的类型为nvarchar,包含条件结果和布尔运算符。 因此,上述数据可以格式化如下:
1 TRUE AND TRUE OR TRUE NULL
2 FALSE OR FALSE NULL
3 TRUE OR FALSE AND FALSE NULL
4 FALSE AND TRUE NULL
5 FALSE AND TRUE AND TRUE NULL
在决赛中,'Expression'字段可能包含AND / OR,多个TRUE和FALSE。
正如我所说,我需要的是计算表达式值 - 检查它是真还是假。
整个逻辑都在程序中,我可以为每一行构建动态sql并对其进行处理, 但在我的实际情况中,我会有几行,所以创建循环并为每一行调用execute_sql听起来不是很好。
是否有任何内置函数可以帮助我评估这些字符串,因为我无法使用交叉应用程序。
答案 0 :(得分:1)
为什么不在插入时评估它而不是在查询时?一位(结果)的成本与解析和成本相关的成本执行查询可能是值得的。您可以使用UDF作为触发器(yuk)或计算列(更好)。
您需要做的就是将一些动态SQL链接到某些搜索&替换(我认为)。
如果你的组合数量有限,另一种方法只是查找表达式(减去空白等)和结果。
答案 1 :(得分:1)
我创建了一个用户定义的标量函数,输入参数是用于求值的字符串,返回值为0或1(false或true)。现在,我可以做欲望交叉应用...
以下是示例:
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('0') -- 0
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('1') -- 1
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('1*1') -- 1
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('1+1') -- 1
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('1*0') -- 0
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('0+1*0*1+0*1+0') -- 0
SELECT [dbo].[fn_XxCustom_EvaluateExpression] ('1+1+0+1*0*1+1*1+0') -- 1
我相信有更好的方法,可能使用反向波兰表示法和递归CTE,但没有时间尝试。无论如何,如果有人需要做类似的事情,这是源代码:
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fn_XxCustom_EvaluateExpression]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
DROP FUNCTION [dbo].[fn_XxCustom_EvaluateExpression]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_XxCustom_EvaluateExpression]
(
@Expression NVARCHAR(MAX)
)
RETURNS TINYINT
AS
BEGIN
DECLARE @ExpressionValue TINYINT = 0
IF LEN(@Expression) > 0 AND @Expression IS NOT NULL
BEGIN
-- Checking if this is expression
IF CHARINDEX('+', @Expression) = 0 AND CHARINDEX('*', @Expression) = 0
BEGIN
SET @ExpressionValue = CAST(@Expression AS TINYINT)
END
ELSE
BEGIN
-- Checking if the expression is computed (contains both '*' and '+')
IF CHARINDEX('+', @Expression) > 0 AND CHARINDEX('*', @Expression) > 0
BEGIN
DECLARE @ExpressionsTable TABLE
(
ExpressionID INT IDENTITY(1,1)
,Expression NVARCHAR(MAX)
,ExpressionValue TINYINT
)
DECLARE @XML XML = N'<r><![CDATA[' + REPLACE(@Expression, '+', ']]></r><r><![CDATA[') + ']]></r>'
-- Populate the table with simple expressions (expression which only contains '+' or '*' is simple)
INSERT INTO @ExpressionsTable (Expression)
SELECT DISTINCT RTRIM(LTRIM(T.c.value('.', 'nvarchar(250)')))
FROM @xml.nodes('//r') T(c)
-- Creating a simple expressions with result values
UPDATE @ExpressionsTable
SET ExpressionValue = IIF(CHARINDEX('+', Expression) = 0 AND CHARINDEX('*', Expression) = 0 , Expression, IIF(CHARINDEX('+', Expression) > 0,IIF(CHARINDEX('1', Expression) > 0, 1, 0),IIF(CHARINDEX('0', Expression) > 0, 0, 1)))
-- Evaluating the final expression
SET @ExpressionValue = IIF(CHARINDEX('1', SUBSTRING((SELECT '+' + CAST(ExpressionValue AS VARCHAR(1)) FROM @ExpressionsTable FOR XML PATH('')),2,4000)) > 0, 1, 0)
END
ELSE
-- Checking the type of the simple expression (does it contains '+' or '*')
BEGIN
SET @ExpressionValue = IIF(CHARINDEX('+', @Expression) > 0,IIF(CHARINDEX('1', @Expression) > 0, 1, 0),IIF(CHARINDEX('0', @Expression) > 0, 0, 1))
END
END
END
RETURN @ExpressionValue
END
GO