Benutzer mit den meisten Antworten
Groß und KLeinschreibung in LIKE ignorieren HOWTO?

Frage
-
Hallo Forum,
im MS SQL Server schein es standart zu sein das bei
select * from testtab where name LIKE '%MUELLER%'
und
select * from testtab where name LIKE '%Mueller%'
die gleichen Records zurück geliefert werden egal wie die Groß und kleinschreibung in der Datenbank ist.
Sowiet so gut,
IN Oracle scheint es standart zu sein das Groß und Kleinschreibung beachtet wird.
Kann ich das SQL Statement irgendwie abändern das die gleichen Records zurückkommen,
oder muss ich den entsprechenden Parameter für diese Datenbank ändern? Und wie heist der
Parameter in Oracle dafür?
Gruß und TIA
Michael
Antworten
-
Hallo Michael,
der SQL Server berücksichtigt den Zeichensatz und die Sortierung des jeweiligen Spalte,
wobei, wenn nichts anderes vorgeben wird, die Datenbanksortierung bei der Anlage der
Spalte übernommen wird
Im allgemeinen ist das Latin1_General_CI_AS, was für Case Insensitive, Accent-Sensitive
steht, und so Groß- und Kleinschreibung keine Rolle spielt.Willst Du die Standardvergleiche ändern, musst Du eine COLLATE Klausel angeben, z. B. Latin1_General_CS_AS.
Entweder direkt bei der Spaltenanlage, wenn das immer so (wie bei Oracle) sein soll
oder direkt im Ausdruck:Beachte, dass Indizes u. U. nicht verwendet werden --- berücksichtigt Groß-Klein WHERE name LIKE '%Mueller%' COLLATE Latin1_General_CS_AS -- berücksichtigt Groß-Klein NICHT WHERE name LIKE '%Mueller%' COLLATE Latin1_General_CI_AS
wobei das einleitende "%" ohnehin ein Indexkiller sein kann ;-)Auch bei Oracle kann man Zeichensatz und Sortierung anpassen, siehe u. a.
http://www.lessanvaezi.com/collation-in-oracle-using-nls_sort/
http://stackoverflow.com/questions/507504/accent-and-case-insensitive-collate-equivalent-in-oracleGruß Elmar
- Als Antwort vorgeschlagen Falk Krahl Dienstag, 5. Juli 2011 09:32
- Als Antwort markiert Michael Brockhoff Dienstag, 5. Juli 2011 14:36
Alle Antworten
-
Hallo Michael,
der SQL Server berücksichtigt den Zeichensatz und die Sortierung des jeweiligen Spalte,
wobei, wenn nichts anderes vorgeben wird, die Datenbanksortierung bei der Anlage der
Spalte übernommen wird
Im allgemeinen ist das Latin1_General_CI_AS, was für Case Insensitive, Accent-Sensitive
steht, und so Groß- und Kleinschreibung keine Rolle spielt.Willst Du die Standardvergleiche ändern, musst Du eine COLLATE Klausel angeben, z. B. Latin1_General_CS_AS.
Entweder direkt bei der Spaltenanlage, wenn das immer so (wie bei Oracle) sein soll
oder direkt im Ausdruck:Beachte, dass Indizes u. U. nicht verwendet werden --- berücksichtigt Groß-Klein WHERE name LIKE '%Mueller%' COLLATE Latin1_General_CS_AS -- berücksichtigt Groß-Klein NICHT WHERE name LIKE '%Mueller%' COLLATE Latin1_General_CI_AS
wobei das einleitende "%" ohnehin ein Indexkiller sein kann ;-)Auch bei Oracle kann man Zeichensatz und Sortierung anpassen, siehe u. a.
http://www.lessanvaezi.com/collation-in-oracle-using-nls_sort/
http://stackoverflow.com/questions/507504/accent-and-case-insensitive-collate-equivalent-in-oracleGruß Elmar
- Als Antwort vorgeschlagen Falk Krahl Dienstag, 5. Juli 2011 09:32
- Als Antwort markiert Michael Brockhoff Dienstag, 5. Juli 2011 14:36
-
Hallo Elmar,
also die ersten tests gegen eine Oracle datenbank sahen ersteinmal gut aus:
SELECT *FROM MyTableWHERE NLSSORT(MyField, 'NLS_SORT = Latin_CI') = NLSSORT('BobDillon', 'NLS_SORT = Latin_CI') funktioniert
nur mit LIKE kommen keine ergebnisse zurück:
SELECT *FROM MyTableWHERE NLSSORT(MyField, 'NLS_SORT = Latin_CI') LIKE NLSSORT('Bob%', 'NLS_SORT = Latin_CI')
hast du eine Ahnung woran das liegen kann?
Gruß
Michael
-
Hallo Michael,
ich habe mich zwar länger von Oracle ferngehalten. An Deiner Stelle würde ich durcharbeiten:
5 Linguistic Sorting and String Searching
dort wird Thema Globalisierung ausführlich behandelt.
Und auch wenn Oracle (wie üblich) andere Wege geht, so weit ich einschätzen kann,
ist Gleiches erreichbar wie bem SQL Server.Es ist ja nicht so, als ob man vom IBM-MainFrame-Zeitalter nicht wegkommen könnte,
als die Welt in 26 (Groß-)Buchstaben gefasst wurde ;-)Gruß Elmar
-
Hallo Elmar,
eigentlich sollte es so gehen:
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;
SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;
SQL> SELECT ename FROM emp1 WHERE ename LIKE 'McC%e';
ENAME
----------------------
McCoye
MccathyeNur bei meiner Oracle Express Datenbank scheint das nicht zu gehen
Version im Testeinsatz:
Oracle Database Express Edition (Oracle Database XE)
Gruß Michael
- Bearbeitet Michael Brockhoff Dienstag, 5. Juli 2011 14:42 typo
-
Hallo Michael,
das ist genau das, was ich vermeiden würde -
und als die schlechteste aller Lösungen ansehe.Mit solchen Funktionen "killst" Du nicht nur jede Index-Verwendung,
sondern verlangst dass Anwender wie zu IBM Lochkartenzeiten arbeiten
=> man könnte gleich alle Daten in Grossbuchstaben eingeben und drucken.Ein Grundverständnis über Zeichensätze sollte man heute für Anwendungen
(nicht nur Datenbanken) erarbeiten, schon gerade weil die Welt immer kleiner wird.
(Was kommt wohl bei UPPER / LOWER in chinesisch raus?)P.S.: Ich hatte leider nicht die Zeit mir eine Oracle Installation anzutun,
wobei es Dir wenig nützen würde, wenn ich mich da schlauer mache ;-)Gruß Elmar
-
Hallo Elmar,
tja ich hätte es ja gerdne so gemacht:
ALTER SESSION SET NLS_COMP=LINGUISTIC GO
ALTER SESSION SET NLS_SORT=BINARY_CI GO
SELECT ename FROM emp1 WHERE ename LIKE 'McC%e' GOIn nem Testtool hat es dann auch gegen eine 'richtige' Oracle Datenbank funktioniert,
nur die Anwendung die den SQL String absetzt setzt den so ab:
dataAdapter.Fill(...
und da kann man wohl nicht mehrere SQL Strings hintereinander (auf einen Schlag) absetzen.
Da die Datensätze nur Deutsch sind und nur varchar und nicht nvarchar (oder wie auch immer das auf Oracle Seite heist).
Und die Suchabfragen nur ab und zu per Hand vom User abgesetzt werden kann ich mit der Krücke ganz gut leben.
Nen Pluspunkt von UPPER ist allerdings ganz klar das das gegen beide Datenbanken identisch funktioniert.
Aber der Punkt mit dem Index ist natürlich auch nicht zu verachten.
Der Benutzer selbst bekommt von seiner Eingabe eh nichts mit, ich
ändern einfach alle seine Eingaben in UPPER, er muss also selbst nicht in Grossbuchstaben die
Suchanfragen eintippen.
Gruß
Michael
-
Hallo Michael,
1.) Die Einstellungen für NLS_COMP, NLS_SORT können nicht nur für eine Sitzung geändert
werden sondern auch global. Und es wäre grundsätzlich empfehlenswert eine passende
Einstellung zu wählen - so wie man es beim SQL Server auch beim Setup macht,
siehe Festlegen und Ändern der ServersortierungDas man Oracle etwas mühseliger konfigurieren muss, sollte einen nicht davon abhalten es zu tun.
Damit dürften 99 % alle Fälle die Einstellungen erledigt sein - denn eine
abweichende Datenbank- oder gar Spaltensortierung ist nur in Sonderfällen notwendig.(Und bei Deinem Vorgehen würde es "knallen", da beim SQL Server eine COLLATION Klausel
notwendig wird, wenn Spalten unterschiedlicher Sortierung verglichen werden -
womit das Ganze nicht mehr portabel wäre; und ich vermute, auch Oracle dürfte verwirrt reagieren ;-).2.) Sinnvoller wäre die Datenbanksysteme deutlicher zu trennen, so dass Du nicht genötigt bist,
den kleinsten gemeinsamen Nenner beim SQL zu finden.Darauf zu spekulieren, dass man mit DataAdapter.Fill hinkommt, wird über erfahrugsgemäß
über kurz oder lang nicht funktionieren, wenn die Anweisungen komplexer werden.3.) .NET (und Windows) arbeitet seit langem mit Unicode und neue Anwendungen
ohne zu entwerfen ist IMHO von vorgestern (Windows 95 lässt grüssen ;-)
(Und Argumente wie Speicherbedarf sind bei Terabyte Platten nicht mehr zu vertreten.)4.) Der Anwender bekommt es schon mit, wenn die SUCHE ein unterschiedliches Verhalten zeigt.
So würde sich z. B. eindeutige Indizes würden sich anders verhalten als die Suche.
UPPER ist nämlich nicht immer so gleich, wie man meint:SELECT CASE WHEN N'Groß' = N'Gross' COLLATE Latin1_General_CI_AS THEN 'Standard Gleich' ELSE 'Standard Ungleich' END, CASE WHEN N'Groß' = N'Gross' COLLATE Latin1_General_CS_AS THEN 'Accent Gleich' ELSE 'Accent Ungleich' END, CASE WHEN UPPER(N'Groß') = UPPER('Gross') COLLATE Latin1_General_CS_AS THEN 'UPPER Accent Gleich' ELSE 'UPPER Accent Ungleich' END, CASE WHEN UPPER(N'Groß') = UPPER('Gross') COLLATE Latin1_General_BIN THEN 'Binär Gleich' ELSE 'Binär Ungleich' END
(Und ich hatte mir vor Jahren schon mal krumme Erklärungen eines Softwareherstellers
dazu anhören müssen - da ging es soweit, das Fehler daraus resultierten).5.) Ob Du da mehr Arbeit reinsteckst, ist letztendlich Deine Sache.
Ich würde aber am Anfang etwas mehr Arbeit reinstecken,
anstatt später auf ewig dran rumzudoktern (und zu fluchen ;-)Gruß Elmar
-
Hallo Elmar,
ersteinmal danke für deine Ausführliche Antwort ;)!
Den Globalen Parameter in der Ini Datei hab ich bis jetzt immer übersehen:
•As initialization parameters on the server You can include parameters in the initialization parameter file to specify a default session NLS environment. These settings have no effect on the client side; they control only the server's behavior. For example: NLS_TERRITORY = "CZECH REPUBLIC"
damit könnte ich es den DB Admins überlassen, aber man kennt das ja die stellen sich manchmal etwas störrisch an.Zu den anderen Punkte, gebe ich dir vollkommen recht, nur habe ich den Source der Anwendung die das SQL Script absetzt nicht im Zugriff. Ich muss also mit dem arbeiten was ich habe.
Trotzdem danke!
Gruß
Michael