PI OLEDB Enterpriseでプレースホルダ(?)を使用することがあります。

たとえば以下クエリです。

SELECT ea.Name, s.Value
FROM [OSItest].[Asset].[ElementHierarchy] eh
INNER JOIN [OSItest].[Asset].[ElementAttribute] ea ON ea.ElementID = eh.ElementID
INNER JOIN [OSItest].[Data].[Snapshot] s ON s.ElementAttributeID = ea.ID
WHERE ea.Name = ?

この?には属性名が入ります。

以下はPI SQL Commanderで’湿度'を指定した場合の結果です。

プレースホルダをテストしたくても、PI SQL Commanderでは使えなかったので、C#でテストしました。 (コンソールアプリです)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
using System.Data;

namespace PIOLEDBEnterpriseTest
{
    class Program
    {
        static void Main(string[] args)
        {
            
            String strServer = "khashimotoe6440";
            String connectionstring = "Provider = PIOLEDBENT; Data Source = " + strServer + "; Integrated Security = SSPI;" ;
            String cmdstring = @"
            SELECT ea.Name, s.Value
            FROM [OSItest].[Asset].[ElementHierarchy] eh
            INNER JOIN [OSItest].[Asset].[ElementAttribute] ea ON ea.ElementID = eh.ElementID
            INNER JOIN [OSItest].[Data].[Snapshot] s ON s.ElementAttributeID = ea.ID
            WHERE ea.Name = ?
            ";
            OleDbConnection Cnn = new OleDbConnection(connectionstring);
            Cnn.Open();
            OleDbCommand Cmd = new OleDbCommand(cmdstring, Cnn);
            Cmd.Parameters.AddWithValue("@p1","湿度");
            OleDbDataAdapter da = new OleDbDataAdapter(Cmd);
            DataSet ds = new DataSet();
            da.Fill(ds, "X");
            int num = ds.Tables["X"].Rows.Count;
            for (int i = 0; i < num; ++i)
            {
                Console.WriteLine(ds.Tables["X"].Rows[i].ItemArray[0] + " : " + ds.Tables["X"].Rows[i].ItemArray[1]);
            }           
            Console.Read();
        }
    }
}

 

実行すると、PI SQL Commanderと同じ結果が得られます。

 

さて、ここでea.Name = ?と1つのアイテムなので、問題ないのですが、属性名をinを利用して複数指定する場合、問題が出てきます。

WHERE ea.Name in (?)とし、Cmd.Parameters.AddWithValue("@p1","湿度,温度");としても動作しません。

解決策は以下に書かれていました。

http://stackoverflow.com/questions/1747452/parameters-in-query-with-in-clause

よって、上記リンクのように?,?と複数のプレースホルダを指定するか、in (クエリ)とする方法が考えられます。

?,?と複数のプレースホルダを用意する場合

 WHERE ea.Name in (?,?)
Cmd.Parameters.AddWithValue("@p1","湿度");
Cmd.Parameters.AddWithValue("@p1", "温度");

inの後ろにクエリを書く場合(この場合プレースホルダは置きません)

SELECT ea.Name, s.Value
FROM [OSItest].[Asset].[ElementHierarchy] eh
INNER JOIN [OSItest].[Asset].[ElementAttribute] ea ON ea.ElementID = eh.ElementID
INNER JOIN [OSItest].[Data].[Snapshot] s ON s.ElementAttributeID = ea.ID
WHERE ea.Name in (
    SELECT ea.Name
    FROM [OSItest].[Asset].[ElementHierarchy] eh
    INNER JOIN [OSItest].[Asset].[ElementAttribute] ea ON ea.ElementID = eh.ElementID
)

上記2つとも動作します。