Alexander (HH): DBI::errstr fetch() without execute()

Beitrag lesen

Moin Moin!

  elsif($aktion eq 'sql'){  
  
Och nö! Laß mich raten: Diese `elsif ($action eq 'irgendwas')`{:.language-perl} stapelst Du vom Fundament bis über das Dach. Sagt Dir der Begriff "Dispatch Table" etwas? [LMGTFY](http://www.google.com/search?&q=dispatch+table+site%3Aperlmonks.org).  
  
  

> ~~~perl
  

> 			read(STDIN, my $st, $ENV{CONTENT_LENGTH});  
> 

Bastelst Du Dir Deine eigene CGI-Schnittstelle? OK, das kann ich im Ansatz nachvollziehen, denn die Interna von CGI sind nicht sonderlich hübsch, voller Altlasten, und das ganze HTML-Gebastel gehört dort überhaupt nicht rein. Aber deswegen gibt es auch einige Alternativen, wie z.B. CGI::Minimal, CGI::Simple, CGI::Lite. Und wenn Du Dich auf ein Framework wie Catalyst oder Plack einläßt, bekommst Du quasi gratis oben drauf noch Support für mod_perl, FastCGI und auch Standalone-Webserver.

  	my $aref = $dbo->{DBH}->selectall_arrayref($st);  
  	if($DBI::errstr){  
  		print "\nFehler: $DBI::errstr\n";  
  	}  
  
Kaputt.  
  
Warum nutzt Du nicht $dbo->{'DBH'}->errstr()? Die globalen Variablen werden quasi ständig überschrieben, die [DBI-Dokumentation warnt davor](http://search.cpan.org/~timb/DBI-1.616/DBI.pm#DBI_Dynamic_Attributes), sie zu benutzen: "Warning: these attributes are provided as a convenience but they do have limitations. Specifically, they have a short lifespan: because they are associated with the last handle used, they should only be used immediately after calling the method that "sets" them. If in any doubt, use the corresponding method call."  
  
Warum nutzt Du nicht [RaiseError](http://search.cpan.org/~timb/DBI-1.616/DBI.pm#RaiseError), wie in der DBI-Doku empfohlen? Damit mußt Du überhaupt nicht mit den error-Methoden herumfrickeln, wenn etwas schief läuft, löst DBI eine Exception aus.  
  

> ~~~perl
  

> 			else{  
> 				print "Ergebnis: \n\n";  
> 				foreach my $r(@$aref){  
> 					print join("\t", @$r),"\n";  
> 				}  
> 			}  
> 

Warum müllst Du den Speicer mit einem Ergebnis voll, dass Du ohnehin zeilenweise benutzen willst?

Nutze eine while-Schleife in Kombination mit fetchrow_arrayref() alias fetch() oder meinetwegen fetchrow_array(). So hast Du immer nur eine Zeile im Speicher.

Für maximale Geschwindigkeit und minimales Umkopieren kannst Du fetch() in Kombination mit bind_col() nutzen, auf die Art schreibt DBI gleich in die Variable, mit der Du (typischerweise innerhalb der while-Schleife) weiterarbeiten willst.

Was bedeutet dieser $DBI::errstr?
Bitte mal um Hinweise,

RTFM. Mehrfach.

Die DBI-Doku ist alles andere als trivial, und man merkt ganz klar, dass das DBI einen weiten Weg gegangen ist. Aber wenn Du mit dem DBI arbeiten willst oder mußt, solltest Du sie mehr als nur einmal gelesen und große Teile verstanden haben. Die Mailing-Liste DBI-Users solltest Du Dir vielleicht auch antun.

Einige Anmerkungen zur DBI-Doku aus langjähriger Erfahrung:

Parameter gehören auf gar keinen Fall ins SQL, sondern haben immer via Platzhalter übergeben zu werden. Das steht leider nicht so deutlich in der DBI-Doku. Deswegen ist die $dbh->quote()-Methode auch vollkommen überflüssig bis gefährlich, und sollte auf lange Sicht verschwinden oder nur noch DBDs zugänglich sein.

$dbh->quote_identifier() ist eine völlig andere Geschichte, aber ebenfalls mit Vorsicht zu genießen. Wenn man sich bei Identifiern auf /^[A-Za-z][A-Za-z0-9_]+$/ beschränkt, kann man sich das Quoting sparen (und zwar komplett, schon gar keine Backticks à la MySQL!), SQL ist case insensitive, und alles ist schön. Mit quote_identifier() wird SQL plötzlich case sensitive (jedenfalls bei einigen RDBMS) und häßliche Dinge können passieren. Auch das steht nicht so deutlich in der Doku.

$dbh->do(...) einerseits und $sth=$dbh->prepare(); $sth->execute(); ... $sth->finish(); andererseits sind nicht zwingend identisch, auch wenn der erste Satz der Beschreibung von $dbh->do() das vermuten läßt. DBDs können durchaus Abkürzungen nehmen, und mindestens neuere Versionen von DBD::ODBC tun das auch.

Viele DBDs unterstützen mittlerweile Unicode, DBD::Oracle schon recht lange, DBD::Pg auch schon eine ganze Weile, DBD::ODBC seit MJE meinen Patch eingepflegt und die Weiterentwicklung übernommen hat, DBD::mysql mittlerweile auch, bei anderen DBDs sieht es etwas schlechter aus. Fast immer muß man wenigstens über ein DBD-spezifisches Attribut den Unicode-Support einschalten, denn aus Kompatibilitätsgründen ist der Standardwert aus. Manche DBs brauchen außerdem noch ein paar Extras in den DB-Einstellungen (z.B. Oracle und PgSQL). Wenn Unicode einmal aktiviert ist, kann man direkt Unicode in die DB schreiben und wieder lesen, ohne sich mit Encode herumschlagen zu müssen. Und andere Tools, die auf der DB aufsetzen (und natürlich die DB selbst), sehen ebenfalls Unicode und nicht irgendwelche wirren Byte-Folgen.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".