Powershell Script soll keine Duplikate in der DB erstellen?
Hallo,
ich habe ein Powershell Script welches Daten von API Seiten abfragt und diese in eine Datenbank schreibt. Das funktioniert soweit auch. Leider dupliziert das Script bei jeder Abfrage die Daten in der Datenbank, dabei sollen schon vorhandene Datensätze nicht erneut geschrieben werden sondern nur neue, die auf der abgefragten Seite hinzugekommen sind. Habe verschiedene Lösungswege versucht aber nichts funktionierte. Entweder schrieb das Script trotzdem Duplikate oder es gab andere Fehlermeldungen... Kann mir jemand sagen wie ich das lösen kann?
Das Script:
# Konfiguration der Vote-Server
$voteServer = @(
@("LINKZURAPI1", "1.Server", 3),
@("LINKZURAPI2", "2.Server", 3)
)
# MySQL-Datenbank
$MySQLHost = "localhost"
$MySQLPort = "3306"
$MySQLDatabase = "test"
$MySQLUser = ""
$MySQLPassword = ""
# Funktion zum Überprüfen und Erstellen der Tabelle
function Ensure-DatabaseTable {
param (
[MySql.Data.MySqlClient.MySqlConnection]$connection
)
$tableName = "votings"
$query = @"
CREATE TABLE IF NOT EXISTS $tableName (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
voteAt DATE,
server VARCHAR(100),
site VARCHAR(100),
received TINYINT(4) DEFAULT 0,
coins INT DEFAULT 0
);
"@
$command = $connection.CreateCommand()
$command.CommandText = $query
$command.ExecuteNonQuery() | Out-Null
}
# Verbindung zur Datenbank
try {
[System.Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\MySQL\MySQL Connector NET 8.2.0\MySQL.Data.dll") | Out-Null
$constr = "server=$($MySQLHost);port=$($MySQLPort);database=$($MySQLDatabase);user id=$($MySQLUser);password=$($MySQLPassword)"
$con = New-Object MySql.Data.MySqlclient.MySqlConnection($constr)
$maxAttempts = 5
$attempts = 0
while ($attempts -lt $maxAttempts -and $con.State -ne 'Open') {
try {
$con.Open()
} catch {
Write-Output "Fehler beim Verbinden zur Datenbank: $_"
}
$attempts++
Start-Sleep -Seconds 1
}
# Verbindung erfolgreich oder nicht
if ($con.State -ne 'Open') {
Write-Output "Verbindung zur Datenbank konnte nicht hergestellt werden."
Exit
} else {
Write-Output "Datenbankverbindung erfolgreich geöffnet."
}
# Abfrage für die Vote Links
foreach ($server in $voteServer) {
try {
Write-Output "Starte Abfrage für Server $($server[1])"
$r = Invoke-RestMethod -Method Get -Uri $server[0]
if ($r.GetType().FullName -eq "System.String") {
Write-Output "Abruf vom Vote-Server fehlgeschlagen (String erhalten)."
Continue
}
foreach ($voter in $r.data) {
$votedatum = $voter.timestamp
if (![System.DBNull]::Value.Equals($votedatum) -and $votedatum -ne $null -and $votedatum -ne "") {
try {
$date = [datetime]::ParseExact($votedatum, 'yyyy-MM-ddTHH:mm:ssZ', $null)
$cmd = $con.CreateCommand()
$cmd.CommandText = @"
INSERT INTO votings (name, voteAt, server, site, received, coins)
VALUES (@name, @voteAt, @server, @site, @received, @coins)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
voteAt = VALUES(voteAt),
server = VALUES(server),
site = VALUES(site),
received = VALUES(received),
coins = VALUES(coins)
"@
$cmd.Parameters.AddWithValue("@name", $voter.Username) | Out-Null
$cmd.Parameters.AddWithValue("@voteAt", $date.ToString("yyyy-MM-dd")) | Out-Null
$cmd.Parameters.AddWithValue("@server", $server[1]) | Out-Null
$cmd.Parameters.AddWithValue("@site", 'deutsche-arkserver') | Out-Null
$cmd.Parameters.AddWithValue("@received", 0) | Out-Null
$cmd.Parameters.AddWithValue("@coins", 0) | Out-Null
$cmd.ExecuteNonQuery() | Out-Null
Write-Output "Datensatz für $($voter.Username) erfolgreich eingefügt oder aktualisiert."
} catch {
Write-Output "Fehler beim Einfügen oder Aktualisieren in die Datenbank: $_"
}
}
}
Write-Output "Abfrage für Server $($server[1]) erfolgreich durchgeführt."
} catch {
Write-Output "Fehler bei Server $($server[1]): $_"
Write-Output $_.Exception.InnerException.StackTrace
}
}
} catch {
Write-Output "Fehler beim Verbinden zur Datenbank: $_"
} finally {
# Schließe die Datenbankverbindung am Ende der äußeren Schleife
if ($con.State -eq 'Open') {
$con.Close()
Write-Output "Datenbankverbindung erfolgreich geschlossen."
}
}
2 Antworten
Den Schlüssel auf eindeutig setzen und beim Schreiben die Exception abfangen, falls doppelter Eintragsversuch
Naja, das mit dem "Duplicate Key"-Clause ist ja nett, aber da Dein Primary Key niemals Duplikate erzeugt, ist das halt wirkungslos.
Entweder definierst Du einen anderen Primary Key oder Du musst halt vor jedem INSERT abfragen, ob es (anhand eindeutiger Kriterien) den Datensatz schon gibt.
Die zentrale Frage für Dich lautet also: Woran machst Du fest, ob zwei Datensätze identisch sind oder nicht. Oder anders gefragt: Was identifiziert einen Datensatz eindeutig? Und wenn Du das überlegt hast, ist die Folgefrage: Warum ist das dann nicht der Primary Key der Tabelle?
die ID ist eindeutig wobei nicht von den API Seiten so vorgegeben sind sondern beim schreiben in der Datenbank angelegt werden.
Ich weiß.
von der api her gibt es keine eindeutigen daten woran man es festmachen könnte fürchte ich
Naja, Du sprichst ja von Duplikaten. Wann ist denn aus Deiner Sicht ein Eintrag ein Duplikat? Dafür muss es ja irgendwelche Kriterien geben.
die ID ist eindeutig wobei nicht von den API Seiten so vorgegeben sind sondern beim schreiben in der Datenbank angelegt werden. Also ID 1, 2, 3, usw. von der api her gibt es keine eindeutigen daten woran man es festmachen könnte fürchte ich