Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 06.07.2006 18:21:14 von sylvio runge

Ich habe hier im Zuge eines System-Updates erstmal testweise meine Datenbank von mysql4 nach 5
installiert. Das lief auch "eigentlich" problemlos; auch komplziertere joings usw. keine Probleme...

Allerdings mit der 5.0.22 mysqld Version funktioniert das 2. folgende Konstrukt nicht mehr richtig :


SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
UPPER('r%')
SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
UPPER('ru%')

Er findet also mit mehr als einem Buchstaben ("ru%" z.b.) nix mehr; mit "r%" geht's aber auch bei
5.x probemlos ....

Irgendwie weiß ich nicht was da nicht stimmen soll...;)



S.

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 06.07.2006 18:48:38 von Axel Schwenke

sylvio runge wrote:
>
> Allerdings mit der 5.0.22 mysqld Version funktioniert das 2. folgende
> Konstrukt nicht mehr richtig :
>
> SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
> UPPER('r%')
> SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
> UPPER('ru%')
>
> Er findet also mit mehr als einem Buchstaben ("ru%" z.b.) nix mehr; mit "r%" geht's aber auch bei
> 5.x probemlos ....
>
> Irgendwie weiß ich nicht was da nicht stimmen soll...;)

Ich auch nicht. Wie wäre es denn mal mit einem *nachvollziehbaren*
Beispiel? Was ergibt denn dein UPPER(DECODE(...))?

mysql> select 'AXEL' like upper('ax%');
+--------------------------+
| 'AXEL' like upper('ax%') |
+--------------------------+
| 1 |
+--------------------------+

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.0.23 |
+-----------+


XL

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 06.07.2006 19:32:48 von sylvio runge

Axel Schwenke wrote:
>
> sylvio runge wrote:
> >
> > Allerdings mit der 5.0.22 mysqld Version funktioniert das 2. folgende
> > Konstrukt nicht mehr richtig :
> >
> > SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
> > UPPER('r%')
> > SELECT (...) FROM student WHERE UPPER(DECODE(NAME,'e76a669e075326523c5911553a86abb')) like
> > UPPER('ru%')
> >
> > Er findet also mit mehr als einem Buchstaben ("ru%" z.b.) nix mehr; mit "r%" geht's aber auch bei
> > 5.x probemlos ....
> >
> > Irgendwie weiß ich nicht was da nicht stimmen soll...;)
>
> Ich auch nicht. Wie wäre es denn mal mit einem *nachvollziehbaren*
upps.. sorry (ich hatte das verkuezt damit es übersichtlicher ist)....


Die Tabelle ist definiert
id = bigint (Primary-Key)
Name = blob , BINARY
(restlichen ~20 Felder hier nicht vor interesse)


> Beispiel? Was ergibt denn dein UPPER(DECODE(...))?
>
> mysql> select 'AXEL' like upper('ax%');
> +--------------------------+
> | 'AXEL' like upper('ax%') |
> +--------------------------+
> | 1 |
> +--------------------------+
>
> mysql> select version();
> +-----------+
> | version() |
> +-----------+
> | 5.0.23 |
> +-----------+
>
> XL

mysql-Version ist wie oben schon geschrieben 5.0.22:
+---------------------+
| version() |
+---------------------+
| 5.0.22-Debian_3-log |
+---------------------+
1 row in set (0.00 sec)


also ohne "DECODE" funktionieren Vergleiche problemlos...
+--------------------------+
| 'AXEL' like upper('ax%') |
+--------------------------+
| 1 |
+--------------------------+
1 row in set (0.00 sec)

usw.


Wenn ich aber (mysql 5.x) :

mysql> SELECT id FROM student WHERE UPPER(DECODE(NAME,'e76a669e075b6e034ec5911553a86c')) like
UPPER('r%') ;
+-------------+
| ID |
+-------------+
| 2 |
| 3 |
| 23 |
| 116 |
| 117 |
| 199 |
| 198 |
| 221 |
| 264 |
| 278 |
| 279 |
| 281 |
| 282 |
| 283 |
+-------------+
14 rows in set (0.01 sec)

eintippe, kommen genau 14 Zeilen - korreket (wie unter 4.0.x);


bei dem Ausdruck (unter mysql 5.x):
mysql> SELECT id FROM student WHERE UPPER(DECODE(NAME,'e76a669e075b6e034ec5911553a86c')) like
UPPER('ru%') ;
Empty set (0.00 sec)

aber nichts;

unter 4.0.x (unter 4.0.24_Debian-10sarge2-log, gleiche Daten...) gehts aber:

mysql> SELECT id FROM student WHERE UPPER(DECODE(NAME,'e76a669e075b6e034ec5911553a86c')) like
UPPER('ru%') ;
+-------------+
| ID |
+-------------+
| 2 |
| 3 |
| 23 |
| 117 |
| 278 |
| 279 |
| 281 |
| 282 |
+-------------+
8 rows in set (0.00 sec)


Evtl. hängt das mit :
http://mirror.mirimar.net/mysql/doc/refman/5.1/en/case-sensi tivity.html zusammen?

Habe da schon verschiedenes damit probiert; der scheint aber immer den selben Fehler (besser gesagt
kein Fehler; findet nur nichts wenn suchbegriff länger als 1 Zeichen (+ das "%") bei dem
UPPER/DECODE-Vergleich ist) zu generieren...



Gruss
S.

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 06.07.2006 20:49:19 von sylvio runge

sylvio runge wrote:

[..]
> Evtl. hängt das mit :
> http://mirror.mirimar.net/mysql/doc/refman/5.1/en/case-sensi tivity.html zusammen?
>
> Habe da schon verschiedenes damit probiert; der scheint aber immer den selben Fehler (besser gesagt
> kein Fehler; findet nur nichts wenn suchbegriff länger als 1 Zeichen (+ das "%") bei dem
> UPPER/DECODE-Vergleich ist) zu generieren...
>
scheint es nicht zu sein...

SELECT DECODE(NAME,'e76a669e...*'), UPPER(DECODE(NAME,'e76a669e...*')) from student WHERE id=117;

unter 4.0.x
+-------------------------------------------------+--------- -----------------------------------------------+
| DECODE(NAME,'e76a669e...*c') |
UPPER(DECODE(NAME,'e76a669e...*')) |
+-------------------------------------------------+--------- -----------------------------------------------+
| Rudolph, Stefan | RUDOLPH,
STEFAN |
+-------------------------------------------------+--------- -----------------------------------------------+

unter 5.x
+-------------------------------------------------+--------- -----------------------------------------------+
| DECODE(NAME,'e76a669e...*') |
UPPER(DECODE(NAME,'e76a669e...*')) |
+-------------------------------------------------+--------- -----------------------------------------------+
| Rudolph, Stefan | Rudolph,
Stefan |
+-------------------------------------------------+--------- -----------------------------------------------+



Der igrnoriert also unter 5.x nur das vorgesetzte "UPPER()"... komisch...



4.0.x:
SELECT UPPER('Rudolph, Stefan');
+--------------------------+
| UPPER('Rudolph, Stefan') |
+--------------------------+
| RUDOLPH, STEFAN |
+--------------------------+


unter 5.0.x:
mysql> SELECT UPPER('Rudolph, Stefan');
+--------------------------+
| UPPER('Rudolph, Stefan') |
+--------------------------+
| RUDOLPH, STEFAN |
+--------------------------+
1 row in set (0.00 sec)


scheint nur in der Funktion mit DECODE nicht mehr zu funktionieren... grübel..


S.

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 06.07.2006 22:23:13 von Kai Ruhnau

sylvio runge wrote:
>
> sylvio runge wrote:
>
> [..]
>> Evtl. hängt das mit :
>> http://mirror.mirimar.net/mysql/doc/refman/5.1/en/case-sensi tivity.html zusammen?
>>
>> Habe da schon verschiedenes damit probiert; der scheint aber immer den selben Fehler (besser gesagt
>> kein Fehler; findet nur nichts wenn suchbegriff länger als 1 Zeichen (+ das "%") bei dem
>> UPPER/DECODE-Vergleich ist) zu generieren...
>>
> scheint es nicht zu sein...
>
> SELECT DECODE(NAME,'e76a669e...*'), UPPER(DECODE(NAME,'e76a669e...*')) from student WHERE id=117;
>
> unter 4.0.x
> +-------------------------------------------------+--------- -----------------------------------------------+
> | DECODE(NAME,'e76a669e...*c') |
> UPPER(DECODE(NAME,'e76a669e...*')) |
> +-------------------------------------------------+--------- -----------------------------------------------+
> | Rudolph, Stefan | RUDOLPH,
> STEFAN |
> +-------------------------------------------------+--------- -----------------------------------------------+
>
> unter 5.x
> +-------------------------------------------------+--------- -----------------------------------------------+
> | DECODE(NAME,'e76a669e...*') |
> UPPER(DECODE(NAME,'e76a669e...*')) |
> +-------------------------------------------------+--------- -----------------------------------------------+
> | Rudolph, Stefan | Rudolph,
> Stefan |
> +-------------------------------------------------+--------- -----------------------------------------------+
>
>
>
> Der igrnoriert also unter 5.x nur das vorgesetzte "UPPER()"... komisch...
>
> scheint nur in der Funktion mit DECODE nicht mehr zu funktionieren... grübel..

Ich tippe darauf, dass DECODE() sein Ergebnis als einen BINARY string
zurückgibt. Darin ist dann nicht definiert, was kleine und große
Buchstaben sind und wie sie zusammengehören. Dementsprechend
funktioniert das UPPER() nicht und LIKE vergleicht auch binär.

Versuch mal ein UPPER(_latin1 DECODE(NAME,'...')) bzw. das Charcterset
in dem die Daten vorhanden sind.

Ein ähnliches Verhalten, über das ich gestolpert bin, ist unter

Cast Functions and Operators
http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html

beschrieben:

If you use a number in string context, the number automatically is
converted to a BINARY string.

Das erzeugt lustige Effekte beim Sortieren.


Grüße
Kai

--
This signature is left as an exercise for the reader.

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 07.07.2006 08:01:11 von sylvio runge

Kai Ruhnau wrote:

[..]
> >
> > Der igrnoriert also unter 5.x nur das vorgesetzte "UPPER()"... komisch...
> >
> > scheint nur in der Funktion mit DECODE nicht mehr zu funktionieren... grübel..
>
> Ich tippe darauf, dass DECODE() sein Ergebnis als einen BINARY string
> zurückgibt. Darin ist dann nicht definiert, was kleine und große
> Buchstaben sind und wie sie zusammengehören. Dementsprechend
> funktioniert das UPPER() nicht und LIKE vergleicht auch binär.
sieht fast so aus (ist auch bei lower usw.)... und das obwohl überall
der Zeichensatz gleich definiert ist :(

>
> Versuch mal ein UPPER(_latin1 DECODE(NAME,'...')) bzw. das Charcterset
> in dem die Daten vorhanden sind.
also ein
UPPER( CONVERT(DECODE(NAME,'e76a....') USING latin1)
geht z.B. richtig. Leider ist das aber nicht "runterzu" mit 4.0.x kompatibel...
Ist die Frage wie man das umgehen koennte ohne da an jedem ~10. query noch nach
mysql-version extra unterscheiden zu müssen... :(


Gruss
S.

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 07.07.2006 11:32:33 von Axel Schwenke

sylvio runge wrote:
> Kai Ruhnau wrote:
>
>> Ich tippe darauf, dass DECODE() sein Ergebnis als einen BINARY string
>> zurückgibt. Darin ist dann nicht definiert, was kleine und große
>> Buchstaben sind und wie sie zusammengehören. Dementsprechend
>> funktioniert das UPPER() nicht und LIKE vergleicht auch binär.

> sieht fast so aus (ist auch bei lower usw.)... und das obwohl überall
> der Zeichensatz gleich definiert ist :(

Ist er eben nicht. Nach ENCODE() ist es definitiv ein BINARY CHAR() und
nach DECODE() ist die Information, ob das ursprünglich mal _latin1 war,
verloren.

> UPPER( CONVERT(DECODE(NAME,'e76a....') USING latin1)
> geht z.B. richtig. Leider ist das aber nicht "runterzu" mit 4.0.x kompatibel...

Seit 4.1 kannst du gezielt case-insensitive Collations verwenden und
brauchst den Würgaround mit UPPER() sowieso nicht mehr:

SELECT ... WHERE
DECODE(NAME,'e76a669e075326523c5911553a86abb')
LIKE 'ru%' COLLATE latin1_german1_ci

Frühere MySQL-Versionen vergleichen case-insensitiv, sobald einer der
beiden Strings das BINARY Attribut trägt.

> Ist die Frage wie man das umgehen koennte ohne da an jedem ~10. query noch nach
> mysql-version extra unterscheiden zu müssen... :(

Du kannst SQL-Statements so schreiben, daß sie versionsspezifisch sind.

http://dev.mysql.com/doc/refman/5.0/en/comments.html


XL

Re: Unterschied mysql4.0.x zu 5.x bei WHERE .. LIKE ... ?

am 07.07.2006 12:19:06 von Axel Schwenke

Axel Schwenke wrote:

> Seit 4.1 kannst du gezielt case-insensitive Collations verwenden und
> brauchst den Würgaround mit UPPER() sowieso nicht mehr:
....

> Frühere MySQL-Versionen vergleichen case-insensitiv, sobald einer der
> beiden Strings das BINARY Attribut trägt.

Oops. Hier fehlt eine Verneinung. Sobald ein String BINARY ist,
werden Vergleiche case-sensitiv.

/ingrid