2013-04-22 118 views
0

根據表達式,我需要填充'值'字段可以是'0'或'1'(假或真)。T-SQL - 用於評估布爾表達式字符串的Tehnique

以下是簡單的數據:

1 1 * 1 + 1 NULL 
2 0 + 0  NULL 
3 1 + 0 * 0 NULL 
4 0 * 1  NULL 
5 0 * 1 * 1 NULL 

的「表達」字段是類型爲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 

在最後,將「表達」字段可以包含和/或和多個TRUE和FALSE。

我需要的是,我所說的是計算表達式值 - 檢查它是真是假。

整個邏輯在過程中,我可以爲每一行構建動態sql並執行它,但在我真實的情況下,我將擁有行的行,所以創建循環併爲每行調用execute_sql聽起來不是很好解。

是否有任何內置函數可以幫助我評估這些字符串,因爲我無法使用與過程交叉應用。

回答

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 
+0

也許試試這樣的: 'declare @exp varchar(100);選擇@exp ='1 + 1 + 0 + 1 * 0 * 1 + 1 * 1 + 0'; select @exp = replace(REPLACE(@exp,'+','&'),'*','&') select @exp; exec('select'+ @ exp);' – LoztInSpace 2013-04-22 13:53:30

+0

@LoztInSpace我不想使用「exec」語句,因爲我需要這樣做數百次。這是我最初的問題,因爲這個原因,我做了一個標量函數來執行行。另一種方法是創建一個LOOP並在其中執行動態SQL語句。 – gotqn 2013-04-22 14:33:02

1

爲什麼不在評估時插入它而不是在查詢時進行評估?一個位(結果)與解析&執行查詢的成本相比,成本可能是值得的。您可以將其作爲觸發器(yuk)或UDF計算列(更好)。

幾乎所有你需要做的是鏈接一些動態SQL到一些搜索&取代(我認爲)。

如果您的組合數量有限,另一種方式只是對錶達式(減空格等)和結果進行查找。

+0

因爲每個值(0或1)是複雜的選擇語句和檢查的結果。 – gotqn 2013-04-22 10:31:05

+0

您可能想要更新您的問題和示例輸入/輸出列表(特別是標題)。現在我不清楚你有什麼或者你在做什麼。 – LoztInSpace 2013-04-22 10:48:47

+0

我已經設法單獨找到問題。無論如何+1試圖幫助我。 – gotqn 2013-04-22 12:17:58