Archive for Februar, 2008

Stored Procedures

Dienstag, Februar 26th, 2008

Die Diskussion in der Schulklasse um Stored Procedures ist erneut aufgekommen: Im Rahmen unserer so-richtig-Vier-Tier-Hangman-Applikation, die wir für die Schule entwickeln müssen, wurde deren Notwendigkeit in Frage gestellt und diskutiert. Ich bin bekanntlich immernoch ein Verfechter von Stored Procedures für jeden kleinen SQL-Befehl, der gegen die Datenbank abgesetzt wird.

Grund 1: Stored Procedures sind eine definierte Schnittstelle

Stored Procedures definieren zwischen Datenbank und jeder Applikation eine klare Schnittstelle. Mit anderen Worten:

Stored procedures are a contract. (...) The header of the stored procedure defines the parameters that the developer must supply, and the body is where the DBA puts all of their voodoo magic to get the data you requested.

Die treffende Beschreibung stammt aus dem Post Service Oriented Databases auf PaulStovell.NET.

Durch die Stored Procedure wird es leichter, die Datenbank zu erweitern, die Daten weiter zu normalisieren, total anders abzulegen oder Felder umzubenennen. Ausserdem können Optimierungen in der Abfrage vorgenommen werden, ohne an der Applikation selbst zu schrauben.

Trotzdem ist es natürlich gefährlich, beliebige Änderungen beispielsweise an Feldnamen vorzunehmen und dann durch die Stored Procedure unter dem alten Namen anzuzeigen, wenn dadurch die Einheitlichkeit der Namen (und somit der Überblick über das Gebilde) verloren geht.

Grund 2: Stored Procedures sind vorkompiliert

Stored Procedures sind vorkompiliert. Somit wird die Abfrage nicht bei jeder Verwendung neu interpretiert weil wieder von der Applikation versandt (zumindest beim Microsoft SQL Server - ich kenne nicht jede DB). Dazu sei ein Artikel SQL Server Stored Procedures von About Databases Guide Site zitiert:

Precompiled execution. SQL Server compiles each stored procedure once and then reutilizes the execution plan. This results in tremendous performance boosts when stored procedures are called repeatedly.

Natürlich macht sich das erst ab einer bestimmten Nutzungsfrequenz und/oder Query-Komplexität bezahlt, aber es schadet auch sicher nicht. :)

Grund 3: Netzwerk-Traffic

Je länger das Query, desto mehr Netzwerkverkehr verursacht die Übermittlung. Ein Stored Procedure Aufruf ist je nach länge wesentlich (oder auch unwesentlich) kürzer.

Grund 4: Mehr Sicherheit durch restriktivere Permissions

Werden Stored Procedures konsequent verwendet, braucht erhält ein Web- oder Service-User, respektive der Benutzer selbst, keine direkten Zugriffsrechte auf Tabellen. Ihm wird lediglich eingeräumt, die Stored Procedures auszuführen, die er benötigt. Der Entwickler oder DBA legt auf diese Weise genau die Queries fest, welche der Benutzer auszuführen hat. Alles andere geht nicht.

Nachtrag: Heute, am 5. Mai, bin ich zu diesem Thema auf simple-talk über "Bad Database Security" von Tony Davis gestossen.

Grund 5: Änderungen an Queries (bei Client-Applikationen)

Bei Applikationen, die auf dem Client laufen und nicht auf dem Server, werden hart codierte Queries mit auf den Client kopiert. In einer neuen Version ändert sich eine Abfrage und ein Benutzer holt sich die neue Version nicht. Es gibt zwei blöde Szenarien:

  1. Blöd: Das Query in der alten Version funktioniert nicht mehr und der Benutzer kann nicht arbeiten. Dies geht in Grund 1 hinein, aber kann natürlich auch mit Stored Procedures passieren, falls sich eine Schnittstelle ändern muss.
  2. Blöder: Das Query liefert Daten, die es nicht liefern sollte. Nehmen wir an, in die Datenbank wird ein neues Feld "IsUserVisible" (Bit) eingefügt. Neu werden den Benutzern nur noch die Einträge angezeigt, welche "IsUserVisible" auf 1/true gesetzt haben. Krasser Häcker Hans-Detlev startet die alte Version und sieht Informationen, die er vielleicht besser nicht sehen sollte.

Was kein Grund ist...

Kein Grund ist meiner Meinung nach das SQL-Injection-Problem. Zwar kann die Tragweite dank eingeschränkten Rechten kleiner sein, aber folgendes kann der geneigte Bastler immer noch machen:

string sql = "EXEC MyStoredProc @Filter = \'" + filter + "\'"

Umgekehrt geht auch folgendes:

string sql = "SELECT * FROM Hubschrauber WHERE HubschrauberId = %1";
// ... und hier mit einem DbCommand-Objekt und Parametern arbeiten

Hm...

Was gibt es dazu für andere Meinungen, Alternativen? Oder wie sieht das auf den verschiedenen DBs aus?

InfoPath, Expressions and 256 Characters

Dienstag, Februar 12th, 2008

For once I'm writing in English, because I am translating English developer slang to German very badly (even worse that I write in English :P) and I'm sure there are more English-speaking developers. Maybe I will write a German version later on.

InfoPath behaves pretty strange when I use expressions that are longer than 256 characters. This morning I worked with rules and conditions on click of a button on an InfoPath form. In my opinion the following is a bug, but it might be a feature too of course:

InfoPath Button Properties Window

If you replace "(long expression here)" with any kind of expression which is longer than 256 characters, everything will go well when you press OK. Now open the properties window again. The expression will be cut to 265 characters. You can paste it again and it will be well again.

The problem is, e.g. you change a condition for a rule that applies on click. Everything will look well, but Apply or OK will not work. As soon as you close the dialog, the changes will be wasted. As a workaround (in German: "Würgaround"), change the expression to "asdf" (or anything that is shorter than the magic 256 characters), make your changes, apply the changes, reopen the window and paste the expression again.