0

式に応じて、「値」フィールドに「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

「式」フィールドは 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

最後に、「式」フィールドには、AND/OR および複数の TRUE と FALSE を含めることができます。

私が言ったように、必要なのは式の値を計算することです-それが真か偽かをチェックします。

ロジック全体はプロシージャー内にあり、行ごとに動的 SQL を作成して実行できますが、実際の状況では何百もの行があるため、ループを作成して行ごとに execute_sql を呼び出すことは適切な解決策とは言えません。

プロシージャで相互適用を使用できないため、これらの文字列を評価するのに役立つ組み込み関数はありますか。

4

2 に答える 2

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
于 2013-04-22T12:16:37.777 に答える
1

クエリを実行するときではなく、挿入するときに評価してみませんか? 1 ビット (結果) のコストとクエリの解析と実行のコストは、おそらくそれだけの価値があります。トリガー (yuk) または UDF を使用した計算列 (はるかに優れています) として実行できます。

ほとんどの場合、動的 SQL を検索と置換にリンクするだけです (私はそう思います)。

組み合わせの数が限られている場合、もう 1 つの方法は、式 (空白などを除く) と結果を参照するだけです。

于 2013-04-22T09:54:19.363 に答える