Leser: 19
1
2
3
4
5
6
7
my $sql = qq(SELECT count(number)
FROM test
where number='22');
my $sth = $dbh->prepare($sql);
$sth->execute();
Perlcode zur Auswertung des Selects,
ggf. gefolgt von dem Insert.
1
2
3
4
5
6
7
8
9
my $sql = qq(set @match = (SELECT count(number)
FROM test
where number='22');
if (@match = '0')
insert into test values(4);
select @match;
select * from test;);
my $sth = $dbh->prepare($sql);
$sth->execute();
2010-12-26T08:54:19 topegEin Datenbank versucht Änderungen so schnell wie möglich allen anderen Nutzern zu Verfügung zu stellen und dabei die Integität der Datensätze zu erhalten. Dem Nutzer werden verschiedenen Hilfsmittel zur Verfügung gestellt, die das unterstützen.
Man kann die Option "AutoCommit=>1" bei DBI setzen und damit ein sofortiges verteilen aller gemachten Aktionen fordern. Ansonsten werden die Änderungen erst allen anderen zur Verfügung gestellt, wenn man $dbh->commit() ausführt oder die Verbindung zur DB schießt.
QuoteDu willst einen Eintrag einfügen wenn er nicht existiert. Dann füge ihn ein und schaue ob einen Fehlermeldung zurück kommt.
1
2
3
4
5
6
7
8
9
my $i = 4;
eval {
my $sql = qq(insert into test values (?));
my $sth = $dbh->prepare($sql);
$sth->execute($i);
};
if ($@) {
print "$@\n";
}
QuoteDu hast alles richtig verstanden. Vielen Dank für deine hilfreichen Infos. Die Spalte ist nun als unique markiert.Wenn es möglich ist einen doppelten Eintrag zu erzeugen, obwohl es nicht gewünscht ist, so stimmt etwas mit den Design der Tabelle nicht.
Oder habe ich etwas an deiner Anforderung nicht verstanden?
Guest gast2010-12-26T08:54:19 topegEin Datenbank versucht Änderungen so schnell wie möglich allen anderen Nutzern zu Verfügung zu stellen und dabei die Integität der Datensätze zu erhalten. Dem Nutzer werden verschiedenen Hilfsmittel zur Verfügung gestellt, die das unterstützen.
Man kann die Option "AutoCommit=>1" bei DBI setzen und damit ein sofortiges verteilen aller gemachten Aktionen fordern. Ansonsten werden die Änderungen erst allen anderen zur Verfügung gestellt, wenn man $dbh->commit() ausführt oder die Verbindung zur DB schießt.
Intressant. Du schreibst "allen anderen Nutzern". Gilt das auch für Prozesse?
Guest gastWürdest du die Rückgabe mit einem eval auswerten?
Code: (dl )1
2
3
4
5
6
7
8
9my $i = 4;
eval {
my $sql = qq(insert into test values (?));
my $sth = $dbh->prepare($sql);
$sth->execute($i);
};
if ($@) {
print "$@\n";
}
Der Code gibt 2 mal folgende Meldung aus:
"DBD::mysql::st execute failed: Duplicate entry '4' for key 'xxx' [for Statement "insert into test values (?)" with ParamValues: 0=4] at ./a.pl line 18"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
my $i = 4; my $sth_ins = $dbh->prepare('insert into test values (?)') || die("Can't prepare Statement!".$dbh->errstr."\n") my $sth_sel = $dbh->prepare('select id from test where id=?') || die("Can't prepare Statement! (".$dbh->errstr.")"); if($sth_ins->execute($i)) { print "Set new value\n"; } else { # einfügen nicht erfolgreich testen ob es den Eintrag schon gibt? # wenn es zu Fehlern kommt stimmt Irgend etwas anderes nicht. my $err=$dbh->errstr; if($sth_sel->execute($i) && $sth_sel->fetchrow_arrayref()->[0] == $i) { # der Eintrag existiert. Die Fehlermeldung muss nicht Ausgeben werden. print "Allready exists\n"; } else { die("Can't insert Value! $err\n") } } $sth_ins->finish; $sth_sel->finish;
2010-12-26T08:54:19 topegMan kann die Option "AutoCommit=>1" bei DBI setzen und damit ein sofortiges verteilen aller gemachten Aktionen fordern. Ansonsten werden die Änderungen erst allen anderen zur Verfügung gestellt, wenn man $dbh->commit() ausführt oder die Verbindung zur DB schießt.
1 2 3 4 5 6 7 8
AutoCommit => 0, my $sql = qq(insert into a values ('2')); my $sth = $dbh->prepare($sql); $sth->execute(); sleep(5); $dbh->commit(); print "exit\n";
QuoteMein Eindruck ist, das man letzlich genau in der Doku der benutzten Engine schauen sollte. Und natürlich testen.* Databases which don't support transactions at all
For these databases, attempting to turn AutoCommit off is a fatal error. commit and rollback both issue warnings about being ineffective while AutoCommit is in effect.
topegDiese Dinge hängen stark von der benutzten DB/DB-Version und der Engine ab. Genauer kann man das hier nachlesen: MySql Man braucht nur in seltenen Fällen extern locken. MySql nimmt einem viele schwierige Themen ab.Man sperrt eine Tabelle nur wenn man viele Aktionen auf diese anwendet bei deren Zwischenschritten man eine nicht funktionstüchtige Tabelle hat. Wenn es nur um das einfügen/ändern geht, so passt die DB schon darauf auf dass die Einträge so schnell wie möglich allen anderen Zugreifenden zur Verfügung stehen.
Mal ein dummes Beispiel wo man sperren würde.
Man habe eine Tabelle mit einer ID und einem Namen. Bei einer Alphabetischen Sortierung der Namen sollen die IDs aufeinander folgend aufsteigend sein. Das bedeutet bei jedem eingefügten Namen müssen alle IDs neu vergeben werden, dass lässt sich ohne weiteres nicht mit einer atomaren Aktion machen (eine nicht aufteilbare Aktion) Bis alle IDs vergeben sind ist die Tabelle nicht funktionstüchtig. (keine IDs oder doppelte IDs vorhanden) Also muss die Tabelle bis zum Abschluss der ID-Vergabe gesperrt werden, damit es zu keinen fehlerhaften Abfrageergebnissen kommt.
Bei einem einfachen einfügen/ändern eines Datensatzes braucht man das nicht, das diese Aktionen atomar sind.
2010-12-24T17:29:05 topegWenn eine Kombination von Spalten einzigartig sein sollen so bilde über diese eine Quersumme (z.B MD5) und Speicher das in einer Spalte die "UNIQUE" ist.
1
2
3
4
5
6
7
8
9
10
$ sqlite3
SQLite version 3.6.23.1
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> CREATE TABLE Foo(a INTEGER, b INTEGER, UNIQUE (a, b));
sqlite> INSERT INTO Foo VALUES (1, 2);
sqlite> INSERT INTO Foo VALUES (1, 3);
sqlite> INSERT INTO Foo VALUES (2, 2);
sqlite> INSERT INTO Foo VALUES (2, 2);
Error: columns a, b are not unique