1

車両がいつ給油されたかを検出するために、C# で定義された次の SQL/Server 関数があります。カーソルをデータの上に戻す必要がないように、最後に使用した燃料のコンテキストを保持します。

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDouble GetFuelRefill(SqlString ID, SqlString FuelLeft)
{
    object _lastID = CallContext.GetData("lastID6");
    object _fuelRefill = CallContext.GetData("fuelRefill");
    double fuelRefill = _fuelRefill == null ? 0.0 : Convert.ToDouble(_fuelRefill);
    object _lastFuelLeft = CallContext.GetData("lastFuelLeft");
    double lastFuelLeft = _lastFuelLeft == null ? 0.0 : Convert.ToDouble(_lastFuelLeft);

    double result = 0.0;

    if ((_lastID == null) || (Convert.ToString(_lastID) != ID.Value) || (_lastFuelLeft == null))
    {
        fuelRefill = 0;
        CallContext.SetData("lastFuelLeft", 0.0);
    }
    else if (!FuelLeft.IsNull)
    {
        double fl = Convert.ToDouble(FuelLeft.Value);
        if ((fl > 0.0) && (lastFuelLeft > 0.0) && ((fl - lastFuelLeft) / fl * 100.0 >= 5.0))
            fuelRefill += fl - lastFuelLeft;
        CallContext.SetData("lastFuelLeft", FuelLeft.Value);
    }
    result = fuelRefill;

    CallContext.SetData("lastID6", ID.Value);
    CallContext.SetData("fuelRefill", fuelRefill);
    return new SqlDouble(result);
}

問題を繰り返す目的で、小さなテスト テーブルを作成しました。

SequenceNo  AssetID   FuelLeft
1           PJ1       50
2           PJ1       49
3           PJ1       48
4           PJ1       98
5           PJ1       95

次に、SQL/Server Management Studio から次のコマンドを実行します。

SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill 
FROM TestTable ORDER BY SequenceNo

これにより、私が期待する次の結果が得られます。

SequenceNo  Refill
1           0
2           0
3           0
4           50
5           50

ただし、VBScript から ADO を使用して同じクエリを実行してみます。

const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
Dim FSO : set FSO = CreateObject("Scripting.FileSystemObject")
Dim Conn : Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=" & DatabaseName & ";Server=" & DatabaseServer
Set Query = CreateObject("ADODB.Recordset")
Query.Open "SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill FROM TestTable ORDER BY SequenceNo", Conn, adOpenForwardOnly, adLockOptimistic
Set f = FSO.CreateTextFile("E:\Temp\Test.TXT", true)
do while not Query.EOF
    f.WriteLine Query("SequenceNo") & ", " & Query("Refill")
    Query.MoveNext
loop
Set FSO = Nothing
Query.Close
Conn.Close

test.txt ファイルには次のものが含まれます。

1, 0
2, 0
3, 0
4, 0
5, 0

さらにデバッグを行うと、クエリの実行中は呼び出しコンテキストが保存されていないように見えますが、その理由と解決方法を誰かが知っているかどうか疑問に思いましたか?

4

1 に答える 1

0

さらに実験を重ねた結果、2 つの解決策が見つかりました。1 つは、次のような単純なストアド プロシージャ内にクエリを配置することでした。

CREATE PROCEDURE sp_Test
AS
BEGIN
    SET NOCOUNT ON;
    SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill 
        FROM TestTable ORDER BY SequenceNo
END

もう 1 つは、クライアント側のカーソルを使用するように VBS コードを変更することでした。

const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
const adUseClient = 3
Dim FSO : set FSO = CreateObject("Scripting.FileSystemObject")
Dim Conn : Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=" & DatabaseName & ";Server=" & DatabaseServer
Set Query = CreateObject("ADODB.Recordset")
Query.CursorLocation = adUseClient
Query.Open "SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill FROM TestTable ORDER BY SequenceNo", Conn, adOpenForwardOnly, adLockOptimistic
Set f = FSO.CreateTextFile("E:\Temp\Test.TXT", true)
do while not Query.EOF
    f.WriteLine Query("SequenceNo") & ", " & Query("Refill") 
    Query.MoveNext
loop
Set FSO = Nothing
Query.Close
Conn.Close
于 2012-12-19T00:22:50.430 に答える