8.06.2010

Access schneidet Memofeld ab

Wenn in einer Anfügeabfrage ein Memofeld verwendet wird über das gruppiert wird, so wird der Text auf 255 Zeichen gekürzt!

5.31.2010

.NET-Zauberzeug

System.Diagnostics.Process.Start (BefehlAlsString)
scheint der extrem leistungsfähige Nachfolger des Shell-Befehls zu sein. Egal ob Excel, Word, Bild, Video, HTML-Adresse oder "mailTo"-Anweisung. Es wird immer das Programm gestartet dass unter Windows mit dem Dateityp verbunden ist.

Zauberzeug!

4.27.2010

ORACLE und Kaufmanns-Und (&)

Das habe ich in 256bit.org Blog gefunden:

Montag, 9. Oktober 2006


Oracle SQL und die Bedeutung verschiedener Sonderzeichen

Momentan arbeite ich an einem etwas größerem Data-Warehouse Projekt und verwalte dort die SQL-Scripte. Dabei kommt es schon vor, dass verschiedene Sachen in die Datenbank eingefügt werden müssen. Letztens stolperte ich dabei über das folgende Phänomen:

SQL> insert into temp_data(name, version) values ('A & P', 3);

Enter value for p: blah

old 1: insert into temp_data values ('A & P', 3)

new 1: insert into temp_data values ('A blah', 3)

1 row created.

Was passiert hier? Nun, Zeichenketten, die mit dem Kaufmannsund anfangen, werden von Oracle als Beginn von Variablennamen definiert. So kann man den Inhalt einer Variablen in ein Textfeld einfügen. Eine Variable kann z.B. so definiert werden:

col spoolfile new_value spoolfile

select '/tmp/logfile_'

to_char(sysdate,'yyyymmdd_HHMI')

'.txt' as spoolfile from dual;

spool &spoolfile

Hier wird in die Variable spoolfile der aktuelle Zeitstempel gespeichert und diese Variable nachher genutzt, um die Log-Datei festzulegen.

Bis hier ist es ok. Wie kann man jetzt ein '&' innerhalb eines Insert-Statements verwenden, obiges Statement funktioniert ja nicht? Man kann Oracle beibringen, dass es keine Variablen-Substitution machen soll. Dies geschieht über ein Set-Statement:

-- Ausschalten des Interpretierens von Variablennamen
-- Dadurch kann & innerhalb von SQL-Statements angegeben werden

set define off

Wenn man jetzt also ein Kaufmannsund braucht und Variablensubstitution nicht ausschalten möchte, ist das schwieriger zu erreichen. Die offensichtliche Lösung besteht darin ähnlich wie in den SELECT-Abfragen die Wildcards % und _ mittels ESCAPE-Zusatz zu maskieren. Die Zeichen % stehen für ein Match auf beliebig viele Zeichen, der Unterstrich matcht genau ein beliebiges Zeichen, wenn man jetzt nach dem Zeichen % sucht, muß man dieses dann eben escapen:

SELECT * FROM testtab WHERE textfeld LIKE '%20@%%' ESCAPE '@';

Hiermit würde man alle Felder finden, in denen die Zeichenkette "20%" vorkommt, egal ob am Anfang oder mittendrin oder am Ende.

Das funktioniert nur leider eben nicht für Insert-Statements:

SQL> insert into temp_data(name,version) values ('A @& P' ESCAPE '@', 3);

Enter value for p: blah

old 1: insert into temp_data values ('A & P', 3)

new 1: insert into temp_data values ('A blah', 3)

1 row created.

Wer sich jetzt fragt, warum ich darüber blogge, reicht doch ein einfaches set define off vor dieser Anweisung und evtl. hinterher ein set define on um die Variablensubstitution aus- und wieder einzuschalten, hat noch nicht folgendes probiert:

col version new_value version

select versionsnr into version from versionstabelle where status='aktiv';

SQL> insert into temp_data(name,version) values ('A & P', &version);

Enter value for p: blah

old 1: insert into temp_data values ('A & P', &version)

new 1: insert into temp_data values ('A blah', 3)

1 row created.


Nein, clevererweise hat sich Oracle hier etwas ganz besonderes einfallen lassen. ESCAPE wäre ja auch zu einfach gewesen. Möchte man unbedingt und auf jeden Fall sowohl Variablen, als auch das Kaufmannsund innerhalb eines Statements haben, muß man diese Zeichenkette als 2 Zeichenketten angeben und diese dann noch konkatenieren. Dabei muß das Kaufmannsund das letzte Zeichen des ersten Teils sein. Das obige Statement sähe dann etwa so aus:

col version new_value version

select versionsnr into version from versionstabelle where status='aktiv';

SQL> insert into temp_data(name,version) values ('A &' || ' P', &version);

old 1: insert into temp_data values ('A & P', &version)

new 1: insert into temp_data values ('A & P', 3)

1 row created.

Ja genau, auf sowas muß man erstmal kommen und in den Oracle-Dokus steht dazu nämlich garantiert nichts, zumindest nichts offensichtliches.

Disclaimer: alle obigen SQL-Statements sind aus meiner Erinnerung abgetippt. Sie sind evtl. nicht ganz syntaktisch korrekt, aber ich hab zuhause halt keine Oracle laufen und so muß ich mein Gedächtnis bemühen.

Ein Dank geht an "The Oracle (tm) Users' Co-Operative FAQ"

1.15.2010

Pfad des Ausführenden

In VB.NET:

Dim aPath As String
Dim aName As String

aName = _
System.Reflection.Assembly.GetExecutingAssembly. _
GetModules()(0).FullyQualifiedName

aPath = System.IO.Path.GetDirectoryName(aName)

'
' Or
'
aPath = System.Reflection.Assembly. _
GetExecutingAssembly.Location


Oder ganz einfach unter VB.NET:
My.Application.Info.DirectoryPath

Quelle: http://www.thescarms.com/dotnet/AppPath.aspx

11.17.2009

Duck-Tape-Programming und Clean-Code

Als auf der letzten PRIO der Begriff "Duck-Tape-Programming" fiel konnte ich mir sofort was drunter vorstellen - wer könnte das nicht.

Natürlich wurde diese Art der Programmierung als unprofessionell und schlecht gebrandmarkt.

Natürlich?? Warum eigentlich?

Wenn ich Duck-Tape höre fällt mir als erstes der Rally-Sport ein. Hier vollbringen Mechaniker mit Duck-Tape wahre Wunder. Für den Laien völlig zerstörte Fahrzeuge werden mit Duck-Tape, Draht und Spuke wieder zusammen geflickt, bestehen noch die nächste Prüfung und vielleicht gewinnt das Team sogar noch die Rally.

Arbeiten diese Mechaniker unprofessionell?
Sind sie schlecht?
Nein, schlecht sind sie garantiert nicht. Die besten Mechaniker schaffen es vielleicht mal Rally-Mechaniker zu werden.

Sie arbeiten nur unter sehr ungewöhnlichen Bedingungen. Ihre Arbeit erfolgt unter enormen Zeit- und Erfolgsdruck mit einem Ergebnis das nur eine sehr begrenzte Zeit durchhalten muss.

Den Gegenpart bildet der Mechaniker in der Werkstatt in die der Familienvater sein Auto bringt: Hier erwarten wir dass in Ruhe ein Ergebnis erzielt wird das "ewig" hält. Niemand will eine Reperatur die zwar schnell geht aber nur circa 100 km hält.

Und hier sehe ich den Zusammenhang zu unserer Arbeit: Die meisten Entwickler (wie auch die meisten Kfz-Mechaniker) arbeiten in einer "Werkstatt" in der es auf Zuverlässigkeit, Langlebigkeit und Robustheit ankommt. Und somit sollten sie so sauber und sorgfältig wie nur irgend möglich arbeiten. Das Ziel sollte immer das bestmögliche und bestwartbare Produkt sein.

Immer mal wieder ist aber auch eine Rally angesagt:
Wenn der Vorstand JETZT Zahlen haben will die einmalig für diesen Forecast gebraucht werden (für den nächsten gelten eh wieder andere Regeln) und man somit "Wegwerf"-Software baut oder Software JETZT um eine ganz spezielle Funktion erweitert werden muss für die Präsentation HEUTE NACHMITTAG - dann ist "Dranflicken" und Improvisieren angeagt. Duck-Tape-Programming ist dann angesagt - ob wir es so nennen oder nicht.

Aber wie auch bei jeder Rally sollte man nicht die Vor- und Nachbereitung vergessen! Rally-Teams bereiten sich mit einem ungeheuren Aufwand von Zeit und Geld auf die extremen Phasen vor. Und jede dieser Phasen wird hinterher ausgewertet und fließt in Verbesserungen und Veränderungen des Fahrzeugs ein.
Und auch das sollten wir uns zum Vorbild nehmen: Nach der letzten Wertungsprüfung alle mit Tape angeklatschten Teile abreißen und die Ursache analysieren warum sie abgerissen sind. Und diese Ursachen dann beheben.

Und damit sind wir wieder in unserer Werkstatt und arbeiten nach dem Clean-Code-Ansatz.

Bis zur nächsten Rally!

11.10.2009

Clean-Code-Developer

Manchmal ist man erstaunt, wenn man Dinge die man fühlt schwarz auf weiß irgendwo liest. Ich habe dann dieses "Genau-Das-Ist-ES"-Gefühl.

Und so geht es mir mit Clean-Code-Developer!
http://clean-code-developer.de/

Jetzt will ich nicht nur MCPD werden sondern auch noch Clean-Code-Developer! Mächtig viel Arbeit ;-)

Und hoffentlich kann ich dann bald immer mal wider diesen Stempel verwenden:

10.20.2009

Access Wunderreperatur

Wenn Access sich "komisch" verhält und die DB Code enthält kann es helfen die Datei mit dem Zeilenparameter /decompile zu öffnen, wieder zu schließen, nochmals mit diesem Schalter zu öffenen und dann zu komprimieren und reparieren.

Zum einen wird die Dateigröße merklich schrumpfen und zum anderen sind bisher (fast) alle Merkwürdigkeiten verschwunden.

10.19.2009

Word: Winzige Schrift in der Dokumentstruktur

Wenn auf einmal (?) die Schrift in der Dokumentenstruktur winzig wird hilft meistens folgendes Vorgehen:
  1. unter ansicht auf gliederung wechseln
  2. unter ansicht wieder auf seitenansicht wechseln
  3. voila -- aber bitte nicht fragemn WARUM es klappt

Lösung gefunden bei http://www.office-loesung.de/ftopic24438_0_0_asc.php

10.01.2009

Geniale Möglichkeit unter ORACLE fortlaufende Zahlen bzw. Datumsintervalle zu erzeugen

Es gibt eine geniale Möglichkeit in ORACLE fortlaufende Nummern zu erzeugen. Die nachfolgend Anweisung erzeugt z.B. die Zahlen 1 bis 100:

select level
from dual
connect by level<=100


Und dies kann man nutzen um damit alle Datumswert in einem Bereich zu erzeugen:

select to_date('2009-07-01','yyyy-mm-dd')+level-1 datum
from dual
connect by level<=to_date('2009-08-01','yyyy-mm-dd')-to_date('2009-07-01','yyyy-mm-dd')


Dank an Uwe Simon!

2.04.2009

Pass-Through doch als Excel exportieren

Weder über das Kontextmenü noch über docmd.TransferSpreadsheet ist Access dazu zu bringen eine Pass-Through-Abfrage zu exportieren.

Wenn man jedoch eine lokale Abfrage "zwischenschaltet" dann geht es.

Name der Pass-Through: Pt1
SQL der lokalen Abfrage: Select * from Pt1

Wichtig ist noch, dass man die lokale Abfrage im SQL-Modus erstellt.

1.30.2009

MS Access GetOption / SetOption

Hier (http://www.access-im-unternehmen.de/fileadmin/download/AccessOptionen.pdf) findet man eine Liste von deutsch/englischen Angaben zu den Optionsnamen in MS Access.

Klasse und Danke an den Autor!

2.26.2008

Excel ist kleinlich

Soll von einem anderen Programm (z.B. Access) aus auf Excel zugegriffen werden, so muss jedes Range und Rows mit dem richtigen Worksheet-Objekt adressiert werden.

Sonst sucht sich Excel bei mehreren Instanzen und benannten Bereichen einen aus bzw. liefert einen Fehler mit ... für _Global fehlgeschlagen.

Tasks finden leicht gemacht

Mit Word-VBA ist das Auffinden von Tasks sehr einfach:



Und hier weniger schön zum rauskopieren:
Sub ZeigeExcel() Dim tskJeder As Task For Each tskJeder In Tasks If InStr(LCase(tskJeder), "excel") Then tskJeder.Visible = True End If NextEnd Sub

2.04.2008

Nützliche Funktionen

Für die Ermittlung von Teilen eines Datums immer wieder gut zu gebrauchen:

EXTRACT (YEAR from sysdate)

Cache leeren:
ALTER SYSTEM FLUSH BUFFER_CACHE; 

1.25.2008

TOAD-Fehler bei Varchar2

TOAD-Version: 8.0.0.47

Im TOAD-Debugger tritt ein Fehler (undeclared identifier) auf, wenn eine Varchar2-Variable mehr als 999 Zeichen enthält und man diese direkt oder mit Watches beobachtet.

Der Code läuft völlig problemlos solange man die Variablen nicht beobachtet.

Eine Lösung zu diesem Problem habe ich noch nicht gefunden.

Benutzerdefinierter Fehler beendet Ausführung und gibt dennoch Meldung aus

Die Anweisung

raise_application_error (-20002, 'do_mcontract2baan - Kein Kundencursor geöffnet!');

erzeugt eine Fehlermeldung. Der Code wird dann nach dieser Meldung fortgesetzt.

Verwendet man

EXCEPTION WHEN others
THEN

so wird zwar die Bearbeitung beendet, aber leider auch die Meldung geschluckt.

Die Lösung:

Es wird ein eigener Fehler im PACKAGE definiert:

Fehler_Als_Meldung EXCEPTION;

und diesem dann die gewünschte Fehlernummer zugewiesen:

PRAGMA EXCEPTION_INIT (Fehler_Als_Meldung, -20002);

und eine Behandlungroutine wie folgt implementiert:

EXCEPTIONWHEN fehler_als_meldung
THEN
raise_application_error (-20003, SQLERRM);

Und schon wird die Ausführung des Code unterbrochen und die Meldung ausgegeben!

1.11.2008

n Werte in einer Spalte verknüpft

Immer wieder möchte man die Werte eines Feldes aus n Datensätzen in einem Feld wiederbekommen.
Hier die Function dafür:


Und hier weniger schön formatiert zum rauskopieren:
CREATE OR REPLACE FUNCTION rowconcat(q in VARCHAR2) RETURN VARCHAR2 IS
ret VARCHAR2(4000);
hold VARCHAR2(4000);
cur sys_refcursor;
BEGIN
OPEN cur FOR q;
LOOP
FETCH cur INTO hold;
EXIT WHEN cur%NOTFOUND;
IF ret IS NULL THEN
ret := hold;
ELSE
ret := ret '; ' hold;
END IF;
END LOOP;
RETURN ret;
END;
/

12.13.2007