SysDa クラスを使用したデータへのアクセス

この記事では、SysDa アプリケーション プログラミング インターフェイス (API) を使用して拡張可能なクエリを作成する方法について説明します。

拡張可能な SysDa API では、X++ で使用できるほとんどすべてのデータアクセス可能性が提供されます。 実際、API は、X++ コンパイラが生成するコードのラッパーです。 したがって、SysDa クラスを使用しても、たとえばQueryRunオブジェクトなどを使用してもオーバーヘッドは発生しません。 さらに、X++ コンパイラがデータアクセス明細書に対して行うチェックは、ユーザーの責任です。 たとえば、グローバルな一意識別子 ( GUID) を整数と比較する where 句を作成します。 X++ コンパイラは、この句をエラーとして診断します。

SysDa API には、カスタムクエリを作成するための広範な API セットが含まれています。 ただし、主なクエリ活動を駆動するもっと小さなタイプには以下のものがあります。

  • 次を選択します: SysDaQueryObjectSysDaSearchObject、および SysDaSearchStatement
  • 次を更新します: SysDaUpdateObject および SysDaUpdateStatement
  • 次を挿入します: SysDaInsertObject および SysDaInsertStatement
  • 次を削除します: SysDaQueryObjectSysDaDeleteObject、および SysDaDeleteStatement

次のセクションでは、クエリのタイプの例と、それがサポートするカスタマイズについて説明します。 この例では、TestTable という名前のテーブルを使用します。 このテーブルには、stringField という名前の文字列フィールドと、intField という名前の整数フィールドの2つのフィールドがあります。

クエリの選択

選択 クエリを実行するには、次の手順を実行します。

  1. 指定されたレコードを含むテーブルインスタンスを指定する、SysDaQueryObject オブジェクトを作成および構成します。
  2. Sysdasearchobject オブジェクトを作成し、SysDaQueryObject オブジェクトをコンストラクターに渡します。
  3. Sysdasearchobject オブジェクトを SysDaSearchStatement.findNext() メソッドに渡すことで、クエリの結果を繰り返します。

次の例では、intField<= 5 である TestTable のすべての行を検索します。

// t is the table buffer that will hold the result.
TestTable t;

// Create the query.
var qe = new SysDaQueryObject(t);

// Add clauses to the query. First the projection.
var s = qe.projection()
    .add(fieldStr(TestTable, intField))
    .add(fieldStr(TestTable, stringField));

// At this point the query is:
// intField, stringField FROM TestTable

// Add a where clause to include rows where intField is <= 5.
qe.WhereClause(new SysDaLessThanOrEqualsExpression(
    new SysDaFieldExpression(t, fieldStr(TestTable, intField)),
    new SysDaValueExpression(5)));

// Now the query is:
// intField, stringField FROM TestTable WHERE (TestTable.intField<= 5)

// Order the results by intField.
qe.OrderByClause().addDescending(fieldStr(TestTable, intField));

// Now the query is:
// intField, stringField FROM TestTable ORDER BY intField DESC WHERE (TestTable.intField<= 5)

var so = new SysDaSearchObject(qe);
var ss = new SysDaSearchStatement();

// Enumerate the designated values by using ss.
while (ss.findNext(so))
{
    info(t.stringField);
}

または、Fluent な方法で SysDaQueryObject を構築する、SysDaQueryObjectBuilder を使用できます。

SysDaQueryObjectBuilder は、4 つの JOIN 句すべてサポートしています。

  • INNER
  • OUTER
  • EXISTS
  • NOT EXISTS JOIN

5 つの集計機能 (など) をサポートしています。すなわち、

  • COUNT
  • 合計
  • AVG
  • MIN
  • MAX

WHERE 句および複数の WHERE 句は ANDed をサポートします。

この式は、すべての 7 つの比較式 (言い方) をサポートしています。すなわち、

  • ==
  • <>
  • >
  • >=
  • <
  • <=
  • LIKE

ORDER BY 句をサポートします。

GROUP BY 句をサポートします。

これは、すべての 16 ヒントをサポートしています:

  • firstOnly1
  • firstOnly10
  • firstOnly100
  • firstOnly1000
  • firstFast
  • リバース
  • forUpdate
  • noFetch
  • forceSelectOrder
  • forceNestedLoop
  • forceLiterals
  • forcePlaceholders
  • repeatableRead
  • optimisticLock
  • pessimisticLock
  • generateOnly

次の例では、SysDaQueryObject を構築する 2 つの方法を示します。

<code>
SysDaQueryObjectBuilder::from(exampleTable)
    .firstOnly()
    .innerJoin(exampleJoinedTable)
    .where(exampleTable, fieldStr(ExampleTable, ExampleJoinedTableExampleId)).isEqualTo(exampleJoinedTable, fieldStr(ExampleJoinedTable, ExampleId))
    .where(exampleTable, fieldStr(ExampleTable, ExampleNumber)).isEqualToLiteral(0)
    .toSysDaQueryObject();
</code>
<code>
var exampleTableQueryObject = new SysDaQueryObject(exampleTable);
var exampleJoinedTableQueryObject = new SysDaQueryObject(exampleJoinedTable);
exampleTableQueryObject.firstOnlyHint = SysDaFirstOnlyHint::FirstOnly1;
exampleTableQueryObject.joinClause(SysDaJoinKind::InnerJoin, exampleJoinedTableQueryObject);
exampleJoinedTableQueryObject.whereClause(new SysDaAndExpression(
    new SysDaEqualsExpression(
        new SysDaFieldExpression(exampleTable, fieldStr(ExampleTable, ExampleJoinedTableExampleId)),
        new SysDaFieldExpression(exampleJoinedTable, fieldStr(ExampleJoinedTable, ExampleId))),
    new SysDaEqualsExpression(
        new SysDaFieldExpression(exampleTable, fieldStr(ExampleTable, ExampleNumber)),
        new SysDaValueExpression(0))));
</code>

SysDaQueryExpression を使用すると、OR などの式を有効にできます。

次の例では、OR を使用して SysDaQueryObject を構築します。

<code>
SysDaQueryObjectBuilder::from(exampleTable)
    .wherever(new SysDaOrExpression(
        new SysDaEqualsExpression(
            new SysDaFieldExpression(exampleTable, fieldStr(ExampleTable, ExampleNumber)),
            new SysDaValueExpression(0)),
        new SysDaEqualsExpression(
            new SysDaFieldExpression(exampleTable, fieldStr(ExampleTable, ExampleNumber)),
            new SysDaValueExpression(0))))
    .toSysDaQueryObject();
</code>

明細書の更新

Update 明細書を実行するには、次の手順を実行します。

  1. SysDaUpdateObjectオブジェクトを作成および構成します。
  2. SysDaUpdateObject オブジェクトを SysDaUpdateStatement.execute() オブジェクトに渡すことでデータを更新します。 更新ではデータベースのデータが変更されるため、ttsbegin および ttscommit ステートメントで 実行 するための呼び出しをラップする必要があります。

次の例では、intField = 50 のすべての行について、stringField"fifty" に更新します。

TestTable t;

// Create an update query to find rows where intField = 50.
var uo = new SysDaUpdateObject(t);

// Set stringField to "fifty".
uo.settingClause()
    .add(fieldStr(TestTable, stringField), new SysDaValueExpression("fifty"));

// At this point the update statement is:
// UPDATE_RECORDSET TestTable SETTING stringField=fifty

uo.whereClause(new SysDaEqualsExpression(
    new SysDaFieldExpression(t, fieldStr(TestTable, intField)),
    new SysDaValueExpression(50)));

// Now the update statement is:
// UPDATE_RECORDSET TestTable SETTING stringField=fifty WHERE (TestTable.intField == 50)

// Update the rows.
ttsbegin;
    new SysDaUpdateStatement().execute(uo);
ttscommit;

// Verify the results of the update query.
TestTable t1;
select intField, stringField from t1 where t1.intField == 50;
info("Updated value is: " + t1.stringField);
// Output is: "Updated value is: fifty".

明細書の挿入

挿入明細書を実行するには、次の手順を実行します。

  1. SysDaInsertObject オブジェクトを作成および構成して、挿入中に更新されるフィールドを指定します。
  2. 挿入する行のソースを指定する SysDaQueryObject オブジェクトを作成および構成します。 SysDaQueryObject.予測() のフィールドの順序は、SysDaInsertObject.fields() のフィールドの順序と一致している必要があります。
  3. SysDaQueryObject オブジェクトを、SysDaInsertObject オブジェクトに割り当てます。
  4. 新しい行を挿入するにはSysDaInsertObject オブジェクトを SysDaInsertStatement.executeQuery() メソッドに渡します。

次の例では、行を intField = 40stringField = "en-us" を TestTable に挿入します。

TestTable t;

// Specify the fields in the new row.
var insertObject = new SysDaInsertObject(t);
insertObject.fields()
    .add(fieldStr(TestTable, stringField))
    .add(fieldStr(TestTable, intField));

// At this point the insert statement is:
// INSERT_RECORDSET TestTable(stringField, intField) SELECT

// Retrieve the data to insert from the LanguageTable by using a query.
LanguageTable source;
var qe = new SysDaQueryObject(source);

var s1 = qe.projection()
    .Add(fieldStr(LanguageTable, LanguageId))
    .AddValue(40);

// The query statement is:
// LanguageId, 40 FROM LanguageTable

qe.WhereClause(new SysDaEqualsExpression(
        new SysDaFieldExpression(source, fieldStr(LanguageTable, LanguageId)),
        new SysDaValueExpression("en-us")));

// Now the query is:
// LanguageId, 40 FROM LanguageTable WHERE (LanguageTable.LanguageId == en-us)

// Assign the query to the insert statement.
insertObject.query(qe); 

// The insert statement is now:
// INSERT_RECORDSET TestTable(stringField, intField) SELECT LanguageId, 40 FROM LanguageTable WHERE (LanguageTable.LanguageId == en-us)

var insertStmt = new SysDaInsertStatement();
ttsbegin;
    insertStmt.executeQuery(insertObject);
ttscommit;

// Verify the results of the insert query.
TestTable t1;
select * from t1 where t1.stringField == "en-us";
info(any2Str(t1.intField) + ":" + t1.stringField); 
// The output is "40:en-us".

明細書の削除

明細書の 削除 を実行するには、次の手順を実行します。

  1. Sysdaqueryobject オブジェクトを作成および構成して、削除する行を指定します。
  2. SysDaDeleteObject オブジェクトを作成し、SysDaQueryObject オブジェクトをコンストラクターに渡します。
  3. 行を削除するには SysDaDeleteObject オブジェクトを SysDaDeleteStatement.executeQuery() メソッドに渡します。

次の例では、intField が偶数である行を削除します。

TestTable t;

// Build the query that specifies which rows to delete.
var qe = new SysDaQueryObject(t);

var s = qe.projection()
    .add(fieldStr(TestTable, intField));

// At this point the query is:
// intField FROM TestTable

// Delete rows where intField is even.
qe.WhereClause(new SysDaEqualsExpression(
    new SysDaModExpression(
    new SysDaFieldExpression(t, fieldStr(TestTable, intField)),
    new SysDaValueExpression(2)),
    new SysDaValueExpression(0)));

// Now the query is:
// intField FROM TestTable WHERE ((TestTable.intField MOD 2) == 0)

var ds = new SysDaDeleteStatement();
var delobj = new SysDaDeleteObject(qe);

// The deletion statement, from the SysDaDeleteObject, is:
// DELETE_FROM intField FROM TestTable WHERE ((TestTable.intField MOD 2) == 0)

ttsbegin;
    ds.executeQuery(delobj);
ttscommit;

info("Number of rows after deletion: " + any2Str(t.RowCount()));

SysDa クエリは複数の句をサポートします。

  • whereClausewhere 句は、SysDaQueryExpression から継承したオブジェクトから構築されます。 例はSysDaEqualsExpressionSysDaNotEqualsExpressionSysDaLessThanExpressionがあります。 完全な一覧は、アプリケーションエクスプローラーでフィルタ処理することによって確認できます。
  • orderByClause
  • groupByClause
  • joinClauseKind 付き joinClause
  • joinedQuery
  • settingClause

トラブルシューティング

toString() メソッドを、SysDaQueryObjectSysDaUpdateObjectSysDaInsertObject、およびSysDaQueryObjectオブジェクトに対して使用して、構築している明細書を表示できます。