Production Register
In diesem Szenario wird der SQL Expert Mode beispielhaft für die Handhabung mit gespeicherten Prozeduren (Stored Procedures) dargestellt. Aus der SPS heraus wird eine Verbindung zu einer Datenbank aufgebaut. Mithilfe von einer Stored Procedure werden aus mehreren Tabellen Produktpositionen ausgelesen. Die Bedienung erfolgt über eine Visualisierung.

Kategorie | SQL Expert Mode |
Verwendete Datenbank | |
Kompatible Datenbanken | MS SQL, MySQL, Oracle |
Verwendete SPS Funktionsbausteine | FB_SQLDatabaseEvt, FB_SQLStoredProcedureEvt, FB_SQLResultEvt |
Verwendete SPS Bibliotheken | Tc3_Database, Tc3_Eventlogger |
Download |
In dem MAIN-Programm wird zur Abarbeitung eine sogenannte State-Machine implementiert, in der die verschiedenen SQL-Funktionsbausteine angesprochen werden. Da die Methoden der Funktionsbausteine kein Execute Flag besitzen, muss sichergestellt werden, dass die Methode nach Fertigstellung im nächsten Zyklus nicht noch einmal aufgerufen wird, da sonst der Vorgang wiederholt wird. Dies wird durch die State-Machine auf einfache Weise sichergestellt.
PROGRAM MAIN
VAR
bCONNECT: BOOL;
bEXECUTE: BOOL;
bREAD : BOOL;
bDISCONNECT: BOOL;
R_TRIG1: R_TRIG;
R_TRIG2: R_TRIG;
R_TRIG3: R_TRIG;
R_TRIG4: R_TRIG;
nState: INT;
nState_Connect: INT;
nState_Disconnect: INT;
bConn: BOOL;
bSP: BOOL;
bResult: BOOL;
bData: BOOL;
nDBID: UDINT := 1;
fbSQLDatabase: FB_SQLDatabaseEvt(sNetID:='', tTimeout:=T#10S);
fbSQLStoredProcedure: FB_SQLStoredProcedureEvt(
sNetID:='', tTimeout:=T#10S);
fbSQLResult: FB_SQLResultEvt(sNetID:='', tTimeout:=T#10S);
arrParameter: ARRAY [0..0] OF ST_SQLSPParameter;
nCustomerID: DINT := 12345;
nRecordStartIndex: UDINT;
stRecordArr: ARRAY [1..20] OF ST_Record;
nRecs: UDINT;
ipResultEvt : Tc3_Eventlogger.I_TcMessage;
bError : BOOL;
nEventID: UDINT;
sEventClass : STRING(255);
sEventMsg : STRING(255);
END_VAR
R_TRIG1(CLK:=bCONNECT);
IF R_TRIG1.Q AND nState = 0 THEN
nState := 1;
END_IF
R_TRIG2(CLK:=bEXECUTE);
IF R_TRIG2.Q AND nState = 0 THEN
nState := 2;
END_IF
R_TRIG3(CLK:=bREAD);
IF R_TRIG3.Q AND nState = 0 THEN
nState := 3;
END_IF
R_TRIG4(CLK:=bDISCONNECT);
IF R_TRIG4.Q THEN
nState := 4;
END_IF
CASE nState OF
0:(*Idle*)
;
1: // Connect to database and create stored procedure instance
CASE nState_Connect OF
0:
IF fbSQLDatabase.Connect(hDBID:= nDBID) THEN
ipResultEvt := fbSQLDatabase.ipTcResult;
bConn := NOT fbSQLDatabase.bError;
IF bConn THEN
nState_Connect := 1;
ELSE
nState:=200;
END_IF
END_IF
1:
arrParameter[0].sParameterName := '@Customer_ID';
arrParameter[0].eParameterDataType :=
Tc3_Database.E_ColumnType.Integer;
arrParameter[0].eParameterType := E_SPParameterType.Input;
arrParameter[0].nParameterSize := SIZEOF(nCustomerID);
IF fbSQLDatabase.CreateSP('SP_GetAddressByCustomerID',
ADR(arrParameter), SIZEOF(arrParameter),
ADR(fbSQLStoredProcedure)) THEN
ipResultEvt:= fbSQLDatabase.ipTcResult;
bSP := NOT fbSQLDatabase.bError;
nState_Connect:=0;
nState := 200;
END_IF
END_CASE
2: // Execute stored procedure
IF fbSQLStoredProcedure.ExecuteDataReturn(
pParameterStrc:= ADR(nCustomerID),
cbParameterStrc:= SIZEOF(nCustomerID),
pSQLDBResult:= ADR(fbSQLResult)) THEN
ipResultEvt:= fbSQLStoredProcedure.ipTcResult;
MEMSET(ADR(stRecordArr),0,SIZEOF(stRecordArr));
bResult := NOT fbSQLStoredProcedure.bError;
nState := 200;
END_IF
3: // Read customer positions
IF fbSQLResult.Read(nRecordStartIndex, 20, ADR(stRecordArr),
SIZEOF(stRecordArr), TRUE, FALSE) THEN
ipResultEvt:= fbSQLResult.ipTcResult;
bData := NOT fbSQLStoredProcedure.bError;
nRecs := fbSQLResult.nDataCount;
nState := 200;
END_IF
4:// Disconnect all
CASE nState_Disconnect OF
0:
IF bData THEN
IF fbSQLResult.Release() THEN
nState_Disconnect := 1;
END_IF
ELSE
nState_Disconnect := 1;
END_IF
1:
IF bSP THEN
IF fbSQLStoredProcedure.Release() THEN
nState_Disconnect := 2;
END_IF
ELSE
nState_Disconnect := 2;
END_IF
2:
IF bConn THEN
IF fbSQLDatabase.Disconnect() THEN
nState_Disconnect := 3;
END_IF
ELSE
nState_Disconnect := 3;
END_IF
3:
bData := FALSE;
bSP := FALSE;
bConn := FALSE;
bResult := FALSE;
sEventClass := "";
sEventMsg := "";
nEventID := 0;
bError := FALSE;
nState_Disconnect := 0;
nState := 0;
END_CASE
200:
IF ipResultEvt.RequestEventText(1033, sEventMsg, SIZEOF(sEventMsg)) THEN
nState := 201;
END_IF
201:
IF ipResultEvt.RequestEventClassName(1033, sEventClass, SIZEOF(sEventClass)) THEN
nEventID := ipResultEvt.nEventId;
bError := (ipResultEvt.eSeverity = TcEventSeverity.Error) OR
(ipResultEvt.eSeverity = TcEventSeverity.Critical);
nState:=0;
END_IF
END_CASE
Die einzelnen Schritte des Ablaufs können in den einzelnen States in der SPS nachvollzogen werden. Zur einfachen Handhabung stehen boolsche Flags zur Verfügung.
- bConnect: Verbindung wird mit der Datenbank aufgebaut
- bExecute: Die Stored Procedure wird ausgeführt und Ergebnisse in den Zwischenspeicher geladen
- bRead: Die Ergebnisse werden in die SPS übertragen
- bDisconnect: Die Verbindung wird geschlossen
Werden diese Schritte nacheinander ausgeführt, wird das Array stRecordArr mit Werten aus der Datenbank gefüllt:
