XML als Datenbank nutzen

Der TwinCAT Database Server bietet die Möglichkeit, eine XML-Datei als Datenbank zu verwenden. Bis auf die „Stored Procedure“-Funktionen werden alle bekannten Funktionsbausteine für das Lesen und Schreiben in eine Datenbank von dem XML-Datenbanktyp unterstützt. Selbst SQL-Befehle, die mit den Funktionsbausteinen FB_DBRecordInsert oder FB_DBRecordSelect abgesetzt werden können, werden vom TwinCAT Database Server interpretiert und entsprechend auf die XML-Datei angewendet.

In diesem Beispiel wird gezeigt, wie eine XML-Datenbank erzeugt, mit dem Baustein FB_DBWrite befüllt und anschließend mit einem SQL-SELECT-Befehl und dem FB_DBRecordSelect wieder ausgelesen wird.

Download: TcDBSrv_InfoSysSamples.zip

XML als Datenbank nutzen 1:

Verwendeter Datenbanktyp

XML

Kompatible Datenbanktypen

MS SQL, MS Compact SQL, MS Access, XML

Verwendete Funktionsbausteine

FB_DBCreate, FB_DBConnectionAdd, FB_DBTableCreate, FB_DBWrite, FB_DBRecordSelect

Einzubindende Bibliotheken

"Tc2_Database", "Tc2_System", "Tc2_Standard", "Tc2_Utilities"

Download Dateiliste

TcDBSrv_InfoSysSamples.tszip

MAIN-Programm

PROGRAM MAIN
VAR
    nState             :BYTE := 0;

    R_TRIG1            : R_TRIG;
    bSTART             : BOOL;

    nCounter           : INT;

    FB_FileDelete1     : FB_FileDelete;
    FB_DBCreate1       : FB_DBCreate;
    FB_DBConnectionAdd1: FB_DBConnectionAdd;
    FB_DBTableCreate1  : FB_DBTableCreate;
    FB_DBWrite1        : FB_DBWrite;
    FB_DBRecordSelect1 : FB_DBRecordSelect;

    bBusy_Delete       : BOOL;
    bBusy_CreateDB     : BOOL;
    bBusy_ConnAdd      : BOOL;
    bBusy_CreateTable  : BOOL;
    bBusy_WriteDB      : BOOL;
    bBusy_SelectRecord : BOOL;

    bErr               : BOOL;
    nErrid             : UDINT;
    stSQLState         : ST_DBSQLError;
    nRecs              : UDINT;

    nDBid              : UDINT;

    arrTablestrc       : ARRAY [0..3] OF ST_DBColumnCfg :=
     [(sColumnName:='ID',sColumnProperty:='IDENTITY(1,1)',eColumnType:=EDBCOLUMN_BIGINT),
     (sColumnName:='Timestamp',eColumnType:=EDBCOLUMN_DATETIME),
     (sColumnName:='Name',sColumnProperty:='80',eColumnType:=EDBCOLUMN_NTEXT),
     (sColumnName:='Value',eColumnType:=EDBCOLUMN_FLOAT)];

    rTestValue         : LREAL := 1234.56789;
    stRecord           : ST_Record;
END_VAR
CASE nState OF
    0:
        (*To start this sample you have to set a rising edge to the variable bSTART*)
        R_TRIG1(CLK:=bSTART);
        IF R_TRIG1.Q THEN
            nState  := 1;
            FB_FileDelete1(bExecute:=FALSE);
            FB_DBCreate1(bExecute:=FALSE);
            FB_DBConnectionAdd1(bExecute:=FALSE);
            FB_DBTableCreate1(bExecute:=FALSE);
            FB_DBWrite1(bExecute:=FALSE);
            FB_DBRecordSelect1(bExecute:=FALSE);
            bSTART  := FALSE;
            nCounter:= 0;
        END_IF
    1:
        (*It isn't possible to overwrite an existing database file.
         If the database file exist the FB_FileDelete block will delete the file*)
        FB_FileDelete1(
            sNetId   := ,
            sPathName:= 'C:\TwinCAT\TcDatabaseSrv\Samples\XMLTestDB.xml',
            ePath    := PATH_GENERIC,
            bExecute := TRUE,
            tTimeout := T#5s,
            bBusy     => bBusy_Delete,
            bError    => ,
            nErrId    => );

        IF NOT bBusy_Delete THEN
            nState   := 10;
        END_IF
    10:
        (*It isn't possible to overwrite an existing database file.
         If the database file exist the FB_FileDelete block will delete the file*)
        FB_FileDelete1(
            sNetId   := ,
            sPathName:= 'C:\TwinCAT\TcDatabaseSrv\Samples\XMLTestDB.xsd',
            ePath    := PATH_GENERIC,
            bExecute := TRUE,
            tTimeout := T#5s,
            bBusy     => bBusy_Delete,
            bError    => ,
            nErrId    => );

        IF NOT bBusy_Delete THEN
            FB_FileDelete1(bExecute:=FALSE);
            nState   := 2;
        END_IF
    2:
        (*The FB_DBCreate block will create the database file
         "C:\TwinCAT\TcDatabaseSrv\Samples\XMLTestDB.xml" and
         C:\TwinCAT\TcDatabaseSrv\Samples\XMLTestDB.xsd "*)
        FB_DBCreate1(
            sNetID   := ,
            sPathName:= 'C:\TwinCAT\TcDatabaseSrv\Samples',
            sDBName  := 'XMLTestDB',
            eDBType  := eDBType_XML,
            bExecute := TRUE,
            tTimeout := T#15s,
            bBusy     => bBusy_CreateDB,
            bError    => bErr,
            nErrID    => nErrid);

        IF NOT bBusy_CreateDB AND NOT bErr THEN
            nState   := 3;
        END_IF
    3:
        (*The FB_DBConnectionAdd adds the connection information to the
         XML configuration file*)
        (*ATTENTION: Each database type has his own connection information*)
        FB_DBConnectionAdd1(
            sNetID      := ,
            eDBType     := eDBType_XML,
            eDBValueType:= eDBValue_Double,
            sDBServer   := 'XMLTestDB',
            sDBProvider := ,
            sDBUrl      := 'C:\TwinCAT\TcDatabaseSrv\Samples\XMLTestDB.xml',
            sDBTable    := 'myTable',
            bExecute    := TRUE,
            tTimeout    := T#15s,
            bBusy        => bBusy_ConnAdd,
            bError       => bErr,
            nErrID       => nErrid,
            hDBID        => nDBid);

        IF NOT bBusy_ConnAdd AND NOT bErr THEN
            nState := 4;
        END_IF
    4:
        (*The FB_DBTableCreate create the table "myTable"*)
        FB_DBTableCreate1(
            sNetID      := ,
            hDBID       := nDBid,
            sTableName  := 'myTable',
            cbTableCfg  := SIZEOF(arrTablestrc),
            pTableCfg   := ADR(arrTablestrc),
            bExecute    := TRUE,
            tTimeout    := T#15s,
            bBusy        => bBusy_CreateTable,
            bError       => bErr,
            nErrID       => nErrid);

         IF NOTbBusy_CreateTable AND NOT bErr THEN
            nState      := 5;
        END_IF
    5:
        (*The FB_DBWrite write five times the value of the plc variable "rTestValue" to
         the database table "myTable"*)
        FB_DBWrite1(
            sNetID          := ,
            hDBID           := nDBid,
            hAdsID          := 1,
            sVarName        := 'MAIN.rTestValue',
            nIGroup         := ,
            nIOffset        := ,
            nVarSize        := ,
            sVarType        := ,
            sDBVarName      := 'rTestValue',
            eDBWriteMode    := eDBWriteMode_Append,
            tRingBufferTime := ,
            nRingBufferCount:= ,
            bExecute        := TRUE,
            tTimeout        := T#15s,
            bBusy            => bBusy_WriteDB,
            bError           => bErr,
            nErrID           => nErrid,
            sSQLState        => stSQLState);

        IF NOT bBusy_WriteDB AND NOT bErr THEN
            FB_DBWrite1(bExecute := FALSE);
            nCounter        := nCounter + 1;
            IFnCounter = 5 THEN
                nState     := 6;
            END_IF
        END_IF
    6:
        (*The FB_DBRecordSelect select one record of the database table "myTable""*)
        FB_DBRecordSelect1(
            sNetID          := ,
            hDBID           := nDBid,
            sSelectCmd      := 'SELECT * FROM myTable WHERE Name = $'rTestValue$'',
            nRecordIndex    := 0,
            cbRecordSize    := SIZEOF(stRecord),
            pDestAddr       := ADR(stRecord),
            bExecute        := TRUE,
            tTimeout        := T#15s,
            bBusy            => bBusy_SelectRecord,
            bError           => bErr,
            nErrID           => nErrid,
            sSQLState        => stSQLState,
            nRecords         => nRecs);

        IF NOT bBusy_SelectRecord AND NOT bErr THEN
            nState          := 0;
        END_IF
    END_CASE

Mit einer positiven Flanke an der Toggle Variable bSTART wird der Ablauf gestartet.

Folgende Dateien werden erzeugt:

XMLTestDB.xml (XML Datenbank Datei)

<?xmlversion="1.0"encoding="UTF-8"?>
<XMLTestDBxmlns:xs="http://www.w3.org/2001/XMLSchema-instance"xs:noNamespaceSchemaLocation="XMLTestDB.xsd">
  <myTable>
    <rowID="1"Timestamp="2012-05-10T13:48:47"Name="rTestValue"Value="1234.56789" />
    <rowID="2"Timestamp="2012-05-10T13:48:47"Name="rTestValue"Value="1234.56789" />
    <rowID="3"Timestamp="2012-05-10T13:48:47"Name="rTestValue"Value="1234.56789" />
    <rowID="4"Timestamp="2012-05-10T13:48:47"Name="rTestValue"Value="1234.56789" />
    <rowID="5"Timestamp="2012-05-10T13:48:47"Name="rTestValue"Value="1234.56789" />
  </myTable>
</XMLTestDB>

XMLTestDB.xsd (XML Schema)

<?xmlversion="1.0"?>
<xsd:schemaxmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:simpleTypename="bigint">
    <xsd:restrictionbase="xsd:long" />
  </xsd:simpleType>
  <xsd:simpleTypename="datetime">
    <xsd:restrictionbase="xsd:dateTime" />
  </xsd:simpleType>
  <xsd:simpleTypename="ntext_80">
    <xsd:restrictionbase="xsd:string">
      <xsd:maxLengthvalue="80" />
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleTypename="float">
    <xsd:restrictionbase="xsd:double" />
  </xsd:simpleType>
  <xsd:complexTypename="myTable_Type">
    <xsd:sequence>
      <xsd:elementminOccurs="0"maxOccurs="unbounded"name="row">
        <xsd:complexType>
          <xsd:attributename="ID"type="bigint" />
          <xsd:attributename="Timestamp"type="datetime" />
          <xsd:attributename="Name"type="ntext_80" />
          <xsd:attributename="Value" type="float" />
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:elementname="XMLTestDB">
    <xsd:complexType>
      <xsd:sequenceminOccurs="1"maxOccurs="1">
        <xsd:elementname="myTable"type="myTable_Type" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Voraussetzungen

Entwicklungsumgebung

Zielplattform

Einzubindende SPS Bibliotheken

TwinCAT v3.0.0

PC oder CX (x86)

Tc2_Database