Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Hilfe zu SQLite, Aufbau, Abfrage, Ändern etc.


  • Please log in to reply
84 replies to this topic
fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Hallo,

 

der erste Teil ist schon mal nicht falsch. DANKE :)

 

Ob Dein SELECT im zweiten Teil funktioniert, hängt vom Format des in der User-DB in FullTime abgelegten Werts ab. SelectDate hat jedenfalls den Aufbau 20130627160023. --> Das Format ist genau das gleiche. Dann sollte das so funktionieren.

 

Ein "Helfer-ListView" braucht es nicht. Du kannst die Werte direkt aus dem zurückgegebenen Table-Objekt auslesen und per INSERT in die Archiv-DB schreiben. --> Okay dann kein ListView. Wie ich ein Objekt auslese weiß ich aber nicht. Wie muss ich denn da vorgehen? Ich hab doch das Ergebis des SELECT in Result. Ist Result das Objekt? Wie geh ich da vor?

 

Danach wäre vielleicht auch noch ein DELETE mit den Auswahlkriterien der SELECT in der User-DB angebracht. ---> Hier wüsste ich auch nicht wie ich vorgehen sollte. Über ein ListView würde ich anhand der ID's  die passenden Rows löschen lassen. Das geht ja dann so nicht. Keine Ahnung wie ich da ran gehen soll.

 

Für mich ist das mit Objekten eine völlig neue Welt. Ich weiß nicht wie man damit umgehen muss, wie man sie anspricht, ausliest oder verarbeitet.



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Ein "Helfer-ListView" braucht es nicht. Du kannst die Werte direkt aus dem zurückgegebenen Table-Objekt auslesen und per INSERT in die Archiv-DB schreiben. --> Okay dann kein ListView. Wie ich ein Objekt auslese weiß ich aber nicht. Wie muss ich denn da vorgehen? Ich hab doch das Ergebis des SELECT in Result. Ist Result das Objekt? Wie geh ich da vor?

 

Schau Dir mal ShowTable() in diesem Post genauer an. Wenn Du Table durch Result ersetzt, sollte es klarer werden.

 

Danach wäre vielleicht auch noch ein DELETE mit den Auswahlkriterien der SELECT in der User-DB angebracht. ---> Hier wüsste ich auch nicht wie ich vorgehen sollte. Über ein ListView würde ich anhand der ID's  die passenden Rows löschen lassen. Das geht ja dann so nicht. Keine Ahnung wie ich da ran gehen soll.

 

Vergleiche einfach mal die Beschreibungen zu SELECT und DELETE. Wenn Du dieselben Auswahlkriterien benutzt, löscht ein DELETE all das, was der SELECT geliefert hat.


Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Hi!

 

Hast recht, wenn man sich den Code anschaut kommt man darauf wie es funktionieren sollte.

 

Hier nun der Code:

SelectDate := A_Now ; Aktuelle Zeit
SelectDate += -10, Days ; Von der aktuellen Zeit werden 10 Tage abgezogen.
SQL := "SELECT * FROM " . TableName . " WHERE FullTime <= '" . SelectDate . "' AND Status = '" . StatusArray[2] . "';"
If !DB.GetTable(SQL, Result)
   MsgBox, 16, SQLite Error: GetTable, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
DB.CloseDB(DBFilePath)
DB := New SQLiteDB
If !DB.OpenDB(DBArchivFilePath) {
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
   ExitApp
}
Loop, % Result.RowCount
    {
        Result.Next(Row)
        Loop, % Result.ColumnCount
            {
                Msg%A_Index%:=Row[A_Index]
            }
        DB.Exec("BEGIN TRANSACTION;") ; Beginn der Übertragung
        SQL := "INSERT INTO " . TableNameArchiv . " VALUES('" . Msg1 . "', '" . Msg2 . "', '" . Msg3 . "', '" . Msg4 . "', '" . Msg5 . "', '" . Msg6 . "', 'Geschlossen', '" . Msg8 . "', '" . Msg9 . "', '" . Msg10 . "', '" . Msg11 . "', '0');"
        If !DB.Exec(SQL) ; durchführen des SQL Befehls
            MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
    }
DB.Exec("COMMIT TRANSACTION;") ; Schließen der Übertragung
DB.CloseDB(DBArchivFilePath)
DB := New SQLiteDB
If !DB.OpenDB(DBFilePath) {
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
   ExitApp
}

Das Löschen ist noch nicht mit drin, ich frage mich wie ich hier eine Art sicherung einbauen kann. Ich muss ja sicherstellen, dass nur bei erfolgreichem Speichern des Vorgangs im Archiv der Vorgang in der User DB gelöscht wird.

 

Wenn ich das aber so machen will, müsste ich für jeden Vorgang die Datenbanken mehrmals öffnen und schließen.

Macht das Probleme?

 

Der Ablauf wäre dann:

 

Per SELECT und Bedingungen Zeit sowie geschlossen das Result Objekt erhalten.

 

Im Loop

    Die User DB schließen.

    Die Archiv DB öffnen.

    Vorgang 1 übertragen, wenn kein Fehler gemeldet wird dann:

        Archiv DB schließen.

        User DB öffnen.

        Vorgang mit ID "Msg1" löschen, wenn kein Fehler gemeldet wird dann beginnt das ganze von vorne.

 

Wird beim Übertragen von Vorgang 1 aber ein Fehler gemeldet ist dann der ganze Eintrag nicht vorhanden oder kann ein Teil vorhanden sein? Muss man diesen dann wieder löschen? In der Beschreibung gibt es eine Rollback Möglichkeit. Kann man diese dazu nutzen? Wenn ja wie?

 

Gleiches beim Löschen, kommt es da zu einem Fehler muss ja trotzdem sichergestellt sein das nicht ein Teil des Eintrags fehlt. Wie geht man da vor?

 

Es scheint mir als wird es ab hier doch sehr komplex. Aber es muss so sein damit nichts kaputt oder verloren geht.

 

Im Admin Tool muss beim einlesen der Archive ins gesammtfile auch geprüft werden ob nicht der Eintrag doch schon vorhanden ist, gibt es dazu einen Befehl? Oder muss man das anhand der Bedingungen machen?

 

In dieser Wiki bekommt man die Befehle schön erklärt: http://de.wikibooks....Daten_speichern

 

Aber so ganz steig ich noch nicht dahinter.

 

Noch eine andere Frage, beim erstellen der DB gibt es diesen Part: PRIMARY KEY(Reminder_ID ASC, KD_Nr ASC, D_ID ASC, Benutzer ASC)

 

Ist einmal ein Vorgang mit z. B. Reminder_ID=abcdef - KD_Nr=123456789 - D_ID=A12345 - Benutzer=fump in der DB Vorhanden darf es keinen gleichen Eintrag geben korrekt? Es reicht aber eine Änderung an einem der Einträge? Wenn also die ID statt abcdef halt aaabbb lautet der Rest aber gleich ist dann ist das okay? Versteh ich das richtig?

 

Ich hoffe ich strapaziere dich nicht zu sehr.

 

MfG

fump

 

 

// EDIT

 

Auf der ersten Seite dieses Threads lese ich gerade, dass du den Rollback schonmal angesprochen hast. Alles nach DB.Exec("BEGIN TRANSACTION;") müsste dann duch DB.Exec("ROLLBACK TRANSACTION;") rückgängig gemacht werden. Erst danach darf dann DB.Exec("COMMIT TRANSACTION;") erfolgen. Richtig?



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Ich würde das etwas anders machen (nicht getestet!):

 

Spoiler

Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Versteh ich das richtig das wenn man ein neues Datenbank-Objekt erstellt man die UserDB gar nicht schließen muss wenn man mit der ArchivDB Arbeiten will?

 

Kannst du mir das mit dem PRIMARY KEY noch erklären bitte?

 

Vielen lieben Dank für den Code. Ich verstehe was da abläuft. Ich kann es aber leider erst heut abend testen. Melde mich dann!



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Versteh ich das richtig das wenn man ein neues Datenbank-Objekt erstellt man die UserDB gar nicht schließen muss wenn man mit der ArchivDB Arbeiten will?

 

Genau!

 

Kannst du mir das mit dem PRIMARY KEY noch erklären bitte?

 

Ein zusammengesetzter PRIMARY KEY ist immer nur in Gänze eindeutig. Sobald eines der beteiligten Felder einen anderen Inhalt hat, ist es ein anderer Key.

 

Vielen lieben Dank für den Code. Ich verstehe was da abläuft. Ich kann es aber leider erst heut abend testen. Melde mich dann!


Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012
;============================================================================
; Tickets, die vor mehr als 10 Tagen geschlossen wurden, werden in die
; Archiv-DB geschoben
;============================================================================
Archiv:
SelectDate := A_Now     ; Aktuelle Zeit
SelectDate += -10, Days ; Von der aktuellen Zeit werden 10 Tage abgezogen.
SQL := "SELECT * FROM " . TableName . " WHERE FullTime <= '" . SelectDate . "' AND Status = '" . StatusArray[2] . "';"
If !DB.GetTable(SQL, Result) {
	MsgBox, 16, Fehler beim Archivieren!, % "SQLite Error: GetTable`r`nMsg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
	Return   ; bei einem Fehler ist hier Schluss!
}
ArchivDB := New SQLiteDB ; <<<<<<<<<<<  Neues Datenbankobjekt für die Archiv-DB erzeugen
If !ArchivDB.OpenDB(DBArchivFilePath) {
	MsgBox, 16, Fehler beim Archivieren!, % "SQLite Error`r`nMsg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
	Return   ; bei einem Fehler ist hier Schluss!
}
ArchivDB.Exec("BEGIN TRANSACTION;") ; Beginn der Übertragung
Loop, % Result.RowCount
	{
		Result.Next(Row)
		SQL := "INSERT INTO " . TableNameArchiv . " VALUES('" . Row[1] . "', '" . Row[2] . "', '" . Row[3] . "', '"	. Row[4] . "', '" . Row[5] . "', '" . Row[6] . "', '" . Row[7] . "', '" . Row[8] . "', '" . Row[9] . "', '"	. Row[10] . "', '" . Row[11] . "', '0');"
		If !ArchivDB.Exec(SQL) ; Durchführen des SQL Befehls
			{
				Fehler := True
				MsgBox, 16, Fehler beim Archivieren!, % "SQLite Error: INSERT`r`nMsg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
				ArchivDB.Exec("ROLLBACK TRANSACTION;") ; Änderungen zurücksetzen
				ArchivDB.CloseDB()
				Result := ""
				Err:=1
				Return   ; bei einem Fehler ist hier Schluss!
			}
	}
ArchivDB.Exec("COMMIT TRANSACTION;") ; Übernehmen der übertragenen Sätze
ArchivDB.CloseDB()
If (Result !="")
	{
		ArchivDB.Exec("BEGIN TRANSACTION;") ; Beginn der Übertragung
		Loop, % Result.RowCount
			{
				SQL := "DELETE FROM " . TableName . " WHERE Reminder_ID='" . Row[1] . "';"
				If !DB.Exec(SQL) ; Durchführen des SQL Befehls
					{
						Fehler := True
						MsgBox, 16, Fehler beim Löschen!, % "SQLite Error: INSERT`r`nMsg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
						DB.Exec("ROLLBACK TRANSACTION;") ; Änderungen zurücksetzen
						Result := ""
						Err:=1
						Return   ; bei einem Fehler ist hier Schluss!
					}
			}
		ArchivDB.Exec("COMMIT TRANSACTION;") ; Übernehmen der übertragenen Sätze
	}
Result := ""
If (Err=1)
	{
		msgbox, 262160, Transaktionsfehler, Beim Archivierungs- oder Löschvorgang kam es zu einem Fehler. Die Datenverarbeitung wurde gestoppt. Bitte versuche es noch einmal! Die Anwendung wird beendet.
		ExitApp
	}
Return

Hi juast me
,

 

habe das Löschen anaalog zum speichern realisiert. Nur wenn die Übertragung ins Archiv geklappt hat, dann hat Result noch einen Inhalt. Nur dann wird das Löschen gestartet. Kommt hier zu einem Fehler, erfolgt auch ein Rollback. Kommt es beim Speichern oder Löschen zu einem Fehler wird die Anwendung am Ende nach einer Meldung beendet.

 

Findest du es gut gelöst so?

 

Eine Sache macht mir schon sorgen. Wenn es zu einem Abbruch kommt beim löschen, und die Anwendung startet erneut, dann sind die Vorgänge ja schon im Archiv. Dennoch würde das Skript versuchen die Daten im Archiv zu speichern. Dabei kommt es unweigerlich zu einem Weiteren Fehler weil die Daten schon vorhanden sind.

Wie würdest du sowas abfangen? Das Archiv einlesen und vergleichen? Oder kann man beim Speichern noch eine WHERE bedingung hinzufügen? So dass nur dann ins Archiv geschrieben wird wenn die ID nicht schon vorhanden ist. Das würde dieses Problem doch lösen oder?

 

MfG
fump



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Guten Morgen,
 
das geht schon mal in eine mögliche Richtung. Ein paar Korrekturen braucht es aber noch:

  • In der DELETE Schleife benutzt Du ArchivDB.Exec(). Die Datenbank ist aber längst geschlossen.
  • In der DELETE Schleife fehlt das Result.Next(Row).
  • Kosmetisch: Deine abschließende Abfrage If (Err=1) wird nie Erfolg haben, weil Du immer dann, wenn Err auf 1 gesetzt wird, die Subroutine mit Return verlässt.

Ich habe mir auch ein paar Gedanken gemacht und bin dabei auf ein interessantes Paar von SQL Anweisung gestoßen: ATTACH / DETACH DATABASE. Damit kann man einer bestehenden Datenbankverbindung weitere Datenbanken hinzufügen und sie auch wieder entfernen. Der Beschreibung nach hat das den Vorteil, dass Transaktionen für alle beteiligten Datenbanken gemeinsam gelten. Wenn man das nutzt, könnte die Archivierungsroutine so aussehen (wenig getestet):

 

Spoiler

 

Voraussetzung dafür ist, dass die Tabellen in der UserDB und der ArchivDB dieselben Felder in derselben Reihenfolge haben und (da bin ich mir allerdings nicht sicher) die Tabellennamen unterschiedlich sind.

 

Edit: Wenn das so nicht geht, solltest Du die ArchivDB offen lassen, bis die DELETE Schleife fehlerfrei beendet ist,  und dann erst den COMMIT für beide Aktionen absetzen.


Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Die Tabellen sind in beiden DB's komplett gleich.

Dein Code funktioniert daher einwandfrei.

 

Vielen Dank dafür!

 

Wobei der andere Code ohne die Fehler ja auch funktionieren würde. Abso so ist es ja wesendlich einfacher. Alles geht in einem Rutsch. Das ist ne super Art und Weise.

 

Damit wäre der User Client eigentlich fertig. Ich werde nun die ganze Sache nochmal durchtesten und den Code nochmal durchschauen.

 

Für den Admin Client hatte ich geddacht, dass wennein User zu viele Vorgänge angelegt hat die er Terminlich nicht mehr schaffen kann, dann man diese Vorgänge an andere User verteilt.

Da ich nur einen Ordner auf einem Netzlaufwerk zur verfügung habe weiß ich noch nicht so ganz wie ich das realisieren kann. Ich muss den Clients ja beiden mitteilen das der Admin Client nun auf deren DB's zugreiffen will.

Mal schauen, vllt. per textdatei, die Clients prüfen per Timer ob textdatei x vorliegt wenn ja dann wird reagiert.

nicht ideal oder?

 

//EDIT:

 

A v i hat dies hier vorhin gepostet.

http://www.autohotke...e-updated-3006/

Sowas lässt sich aber nicht übers Netzwerk nutzen oder?



fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Hi just me,

 

konnte eine Weile nicht am Tool arbeiten aber nun gehts weiter.

 

Ich versuche gerade die Daten der einzelnen Archive in ein gesammtarchiv umzuräumen, anschließend wil ich gerne die User-Archive löschen, dies will mir aber nicht gelingen. Sobald ich die User DB Close kommt beim nachfolgenden ATTACH ein Fehler. Aber warum will mir nicht so ganz einleuchten...

 

Kurze Erklärung zum Code,

die User legen in einem Pfad auf einem Netzlaufwerk einen Oder an der Name ist A_UserName, diesen kompletten Pfad lese ich ein und parse dann durch. Solange ich das DB.Close nicht nutze klappt das alles auch wunderbar. Die Archiv Datei füllt sich, nur bleiben die einzelnen Archive erhalten... beim nächsten mal kommt es dann automatisch zu Fehlern da die Inhalte der einzelnen DB's ja schon im gesammtarchiv vorhanden sind.

 

Hier mein Code:

;============================================================================
; Setzen der Globalen Variablen:
;============================================================================
#NoEnv
#SingleInstance force
#MaxMem, 1024
#Persistent
SetWorkingDir, %A_ScriptDir%
#Include %A_ScriptDir%
SetBatchLines, -1
;============================================================================
; User Einstellungen:
;============================================================================
; INI einlesen
IniRead,globalinipfad, %A_ScriptDir%\funktionen.ini, REMINDER, INIFilePath
IniRead,LANPfad, %A_ScriptDir%\funktionen.ini, REMINDER, LANPfad
IniRead,UserINI, %A_ScriptDir%\funktionen.ini, REMINDER, UserINI
ArchivPath := LANPfad "..\_Archiv\"
; Bezeichnungen der Spalten für die beiden ListViews
ColumnNames := "Reminder ID|KD Nr.|Text ID|ToDo|RR Nr.|WVL Zeitpunkt|Status|ToDo Text|ToDo Erl. Text|Benutzer|FullTime|ShowFlag|FirstUser"
; Status der Vorgänge
StatusArray := ["Offen", "Geschlossen"]
; Inhalt für das DropDown zur ToDo Auswahl
ToDoArray := ["Outbound", "Systemänderung", "Kontrolle"]
ToDoList := ""
For K, V In ToDoArray
   ToDoList .= (A_Index = 1 ? "" : "|") . V
; Abbruchmeldung
AbortProg := "`r`nDas Programm wird beendet!"
; Programname
AppName := "Reminder Admin-Tool"
; Ordner in dem die Datanbank liegt
DBFolder := ArchivPath
; Direkter Pfad zur DB
DBArchivFilePath := DBFolder . "\Reminder-Archiv-" . A_YYYY . ".sql"
; Tabellenname in der DB
TableNameArchiv := "ReminderArchiv"
TableNameArchivAdmin := "ReminderAdmin"

ListViewSearchPfad:=LANPfad "\*.*"
;============================================================================
; ###################### Start Autoexecutebereich ###########################
;============================================================================
If !FileExist(DBFolder) {
   FileCreateDir, %DBFolder%
   If (ErrorLevel) {
      MsgBox, 16, %AppName%, Das Verzeichnis %DBFolder% konnte nicht erstellt werden.%AbortProg%
      ExitApp
   }
}

; Öffnen der Archiv-DB und falls nicht vorhanden erstellen selbiger mit entsprechenden Spalten.
DB := New SQLiteDB
If !DB.OpenDB(DBArchivFilePath) {
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
   ExitApp
}
SQL := "CREATE TABLE IF NOT EXISTS " . TableNameArchivAdmin . " (Reminder_ID, KD_Nr, D_ID, ToDo, RR_Nr, WVL_Zeitpunkt, Status, ToDo_Text, ToDo_Erl_Text, Benutzer, FullTime, ShowFlag, FirstUser, "
     . " PRIMARY KEY(Reminder_ID ASC, KD_Nr ASC));"
If !DB.Exec(SQL)
   MsgBox, 16, SQLite Error1, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
;============================================================================
; ####################### Ende Autoexecutebereich ###########################
;============================================================================

Gui, +HWNDh_MainGui
Gui, +LastFound
Gui, Color, FFFFFF
Gui, Font, S7 CDefault, Verdana
Gui, Add, Button, x996 y2 w220 h16 gRefresh, Refresh
Gui, Add, ListView, x996 y20 w220 h675 vResultsLV1 -Multi NoSortHdr +Sort HWNDh_LV1 +BackgroundD9E7FB -LV0x10, Name|Kurzname
Gui, Add, Tab, x0 y0 w996 h695 +AltSubmit, Infos|Archiv Recherche|Offene Vorgänge verwalten|Livemonitor|Globale Einstellungen
Gui, Tab, 1
Gui, Add, Button, x12 y160 w490 h20 gArchiv, Archivierung starten
Gui, Show, h697 w1219,
GoSub Refresh
Settimer, Refresh, 60000
Return


Archiv:
ArchivAktiveFile =
(
Archivierung ist aktiv!
)
CheckArchivAktive := ArchivPath "archiv.txt"
IfExist %CheckArchivAktive%
	{
		ToolTip, Es ist bereits eine Archivierung aktiv!
		Sleep, 2000
		ToolTip
	}
else
	{
		FileAppend, %ArchivAktiveFile%, %CheckArchivAktive%
		sleep, 50
		Loop, %ListViewSearchPfad%, 2, 1
			ArchivDateiliste := ArchivDateiliste A_LoopFileName "`n"
		
		DBAlias := "UserDB" ; Aliasname für die Archivdatenbank
		
		Loop, parse, ArchivDateiliste, % "`n"
			{
				If A_LoopField =  ; Ignoriert das leere Element am Ende der Liste.
					break
				
				DBUserFilePath := LANPfad A_LoopField "\Reminder-Archiv-" A_LoopField ".sql"
				If FileExist(DBUserFilePath)
					{
						If !DB.Exec("ATTACH DATABASE '" . DBUserFilePath . "' AS " . DBAlias . ";") { ; Archivdatenbank hinzufügen
							SQLiteError(A_ThisLabel, DB, "ATTACH")
						}
						DB.Exec("BEGIN IMMEDIATE TRANSACTION;")
						SQL := "INSERT OR ROLLBACK INTO " . TableNameArchivAdmin . " SELECT * FROM " . DBAlias . "." . TableNameArchiv
						If !DB.Exec(SQL) {
							SQLiteError(A_ThisLabel, DB, "INSERT")
							DB.Exec("ROLLBACK TRANSACTION;") ; Transaktion zurücksetzen (sicher ist sicher)
							DB.Exec("DETACH DATABASE " . DBAlias . ";") ; Archivdatenbank entfernen
							Return
							
						}
						Inserted := DB.Changes  ; nur zum Testen
						DB.Exec("COMMIT TRANSACTION;")   ; Alles ist fehlerfrei gelaufen, die Transaktion kann gültig gesetzt werden.
						If !DB.Exec("DETACH DATABASE " . DBAlias . ";") {  ; Archivdatenbank entfernen
							SQLiteError(A_ThisLabel, DB, "DETACH")
							Return
						}
						;DB.CloseDB(DBUserFilePath)
						Filedelete, DBUserFilePath
						; Nur zum Testen
						MsgBox, 64, Daten wurden archiviert,%DBUserFilePath%`n`n%Inserted% Sätze wurden in das Archiv eingefügt.
					}
			}
		Filedelete, %CheckArchivAktive%
		msgbox ende
	}
Return



Refresh: ; Refresh der ListView
Gui, 1:Default
Gui, ListView, %h_LV1%
BildlisteID:=IL_Create(2,1,0)
IL_Add(BildlisteID, "onlineico.ico")
IL_Add(BildlisteID, "offlineico.ico")
CheckOnlineFile =
(
AreYouOnline?
)
LV_SetImageList(BildlisteID)
; GuiControl, -Redraw, ResultsLV1
Dateiliste:=
Loop, %ListViewSearchPfad%, 2, 1
    Dateiliste := Dateiliste A_LoopFileName "`n"
LV_Delete()
LV_ModifyCol()
LV_ModifyCol(1, 215)
LV_ModifyCol(2, 0)
Loop, parse, Dateiliste, % "`n"
    {
        If A_LoopField =  ; Ignoriert das leere Element am Ende der Liste.
        break
        
        OnlineCheckFile:=LANPfad A_LoopField "\" A_UserName "checkOn.line"
        IfNotExist, %OnlineCheckFile%
            FileAppend, %CheckOnlineFile%, %OnlineCheckFile%
        
        IniRead, name, %UserINI%, user, % A_LoopField, % A_LoopField
        sleep, 25
        
        IfExist %OnlineCheckFile%
            LV_Add("Icon2",name,A_LoopField)
        else
            LV_Add("Icon1",name,A_LoopField)
    }
; GuiControl, +Redraw, ResultsLV1
Return


;============================================================================
; Includes
;============================================================================
#Include Class_SQLiteDB.ahk

Hab mich an deinen Rat gehalten und löse die "Online" Dinge nun per Datei.

Also so: Erstellle Datei X bei User Y, warte kurz, prüfe ob Datei X bei User Y noch existiert, wenn ja dann Offline, wenn nein dann Online. So in etwa :)

 

MfG
fump



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Guten Morgen,

;DB.CloseDB(DBUserFilePath) ; <<< DB.Close() hat keinen Parameter

So sollte eigentlich überhaupt nichts passieren, weil DB.Close() keinen Parameter erwartet und deshalb auch nicht ausgeführt werden sollte. Wenn es doch ausgeführt wird, wird damit aber die per DB.Open() geöffnete Datenbank geschlossen, und das ist die Datenbank für das Gesamtarchiv. Anschließend wäre es schwierig, einer geschlossenen Datenbankverbindung per ATTACH DATABASE weitere Datenbanken hinzuzufügen.

Filedelete, DBUserFilePath

Wenn das nicht klappt, fehlen Dir vielleicht die Löschrechte oder die Datei ist aufgrund der vorangegangenen Aktionen noch geöffnet. Es ist aber auch nicht zwingend notwendig, die Datei zu löschen, es sollte wohl reichen, wenn der Dateiinhalt gelöscht wird. Dafür gibt es eine SQL-Anweisung: Ein 'DELETE FROM DBAlias.TableNameArchiv' innerhalb der Transaktionsklammer könnte helfen. Ab und zu sollten die Dateien dann aber doch gelöscht werden, um sie "aufzufrischen".


Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Ok, ich verstehe warum das DB.Close nun zu den Fehlern führt. Ich dachte er würde so die DB schließen sodass ich sie löschen kann. Aber das war wohl falsch gedacht :)

 

Die Löschrechte habe ich.

 

Es liegt an fehlenden %% :) Es muss natürlich

Filedelete, %DBUserFilePath%

heißen.

 

So klappts dann auch mit dem löschen :)

 

Eine andere Frage.

Kommt es bei den SQL Befehlen zu einem Fehler wird perReturn die verarbeitung im Loop beendet. Endet damit auch der Loop komplett? Oder macht der Loop dann mit dem nächsten weiter?

 

Weitere Fragen:

1. Können mehrer Admins gleichzeitig "lesend" auf die DB zugreiffen?

2. Wenn die DB gerade von mehreren Usern geöffnet ist und einer der Admin will die Archive zusammenlegen, müssen die anderen Admins dann die DB vorher schließen? Oder bekommen die dann probleme bei der weitreren verwendung der DB?

 

Ich frag mich halt gerade ob das Admin Tool überhaupt von mehrern gleichzeitig genutzt werden kann...



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

0. Wenn Du mit der nächsten DB weitermachen willst, musst Du die Return Anweisungen durch Continue ersetzen.

 

1. Parallele lesende Zugriffe sollten möglich sein, im Zweifel einfach ausprobieren.

 

2. Keine Ahnung, s. 1.


Prefer ahkscript.org for the time being.


fump2000
  • Members
  • 591 posts
  • Last active: Nov 11 2015 07:52 AM
  • Joined: 01 Nov 2012

Danke für den Hinweis mit dem Continue.

 

Ich möchte natürlich auch eine Recherche innerhalb des Archives erlauben. Dazu kann der Admin Suchfelder füllen.

 

Dies wären:

ID

KDNr

TextID

ToDo Kategorie

User

 

Anhand des Refresh aus dem Client Script würde ich den SQL Befehl für den Fall das alle komponenten gesucht werden so schreiben:

SQL := "SELECT * FROM " . TableName . " WHERE Reminder_ID='" . RMA_ID . "' AND KD_Nr='" . RMA_KDNr . "' AND D_ID='" . RMA_DID . "' AND ToDo='" . RMA_ToDo . "' AND Benutzer='" . ShortName . "';"

Nun das wäre aber nur dann richtig wenn alle Felder vom Admin genutzt werden.

Muss der String denn immer neu gebaut werden wenn der Admin nur ein oder 2 Felder verwendet?

Kann man Felder leer lassen und trotzdem diesen String verwenden?

 

Sollte ich einfach mal mehr testen anstatt zu fragen? :)



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

 

 

Sollte ich einfach mal mehr testen anstatt zu fragen? happy.png

 

Gute Idee! wink.png

 

In diesem Fall sollte aber auch schon Nachdenken reichen. Wenn Du in der Datenbank mit KD_Nr = '' (d.h. das Feld muss leer sein) nach Sätzen suchst, wie viele Treffer wird die Abfrage wohl liefern?


Prefer ahkscript.org for the time being.