# MySQL: Platzhalter ablegen



## versuch13 (3. Dezember 2008)

Hallo. Ich möchte gerne Platzhalter in den Zellen speichern um anschließend Vergleiche durchführen zu können. (MySQL5)

Also z.B. hat die Spalte den Inhalt 

"foo/%"

nun soll mit dem String "foo/bar" von außen verglichen werden und das sollte einen Treffer ergeben.

Funktioniert soweit auch mit:


```
SELECT `foo` FROM `table` WHERE "foo/bar" LIKE `foo`
```

Allerdings möchte ich auch variable Teile mitten im String haben, also z.B.:

foo/%/bar

bei

foo/boo/bar

gefunden werden. Kann ich dass irgendwie per REGEXP machen? Ist es überhaupt so möglich wie ich es mir vorstelle?

Danke.


----------



## planb2000 (6. Dezember 2008)

Hallo,

heißt deine Spalte denn "foo/bar"

es gibt 2 Operatoren die Du dafür verwenden kannst.


```
-- Finde alle Einträge in denen "foo" an belibieger Stelle vorkommt
select  * from deine_tabelle where column like '%foo%'
-- Finde einträge in denen foo und bar vorkommt
select  * from deine_tabelle
where column like '%foo%'
or column like '%bar%'
-- Mit dem Zeichen "_" begrenzt du die anzahl der zeichen, oder kannst
-- genau bestimmen wo Du den pattern finden möchtest.
select * from deine_tabell
where column like '_2____foo' -- 2 muß an 2ter stelle stehen und foo ab stelle 7
```
Wenn Du die Zeichen '%', "'" finden möchtest mußt du sie mit einem escape zeichen versehen, ich glaube das ist dann der "\" bei Mysql
Hilft Dir das ?

Grüße


----------



## versuch13 (6. Dezember 2008)

planb2000 hat gesagt.:


> heißt deine Spalte denn "foo/bar"



Hey, nein im Beispiel trägt die Spalte den Namen `foo`.




planb2000 hat gesagt.:


> *sql Code: *
> 
> 
> 
> ...



Nein leider nicht, wie gesagt geht es mir um den umgekehrten Weg. Trotzdem danke.


----------



## versuch13 (9. Dezember 2008)

Hey, ich hole das Thema nochmal vor. Weiß dazu sonst wirklich niemand etwas? Bin über jeden Tip dankbar.


----------



## tecla (10. Dezember 2008)

Versteh ich das jetzt richtig?

Deine Spalte heisst "foo", der String heisst "foo/bar".

Dann wäre eine mögliche Abfrage:


```
SELECT foo FROM table WHERE foo LIKE 'foo/%'   OR
foo LIKE '%/bar'
```

Mit REGEXP habe ich keine Erfahrungen.

Grüsse, Tecla


----------



## versuch13 (10. Dezember 2008)

Nein, ich habe von außen den String "foo/bar" und die Spalte heißt `foo` und hat den Inhalt "foo/%", ich zitiere einfach nochmal meinen ersten Beitrag.



versuch13 hat gesagt.:


> Hallo. Ich möchte gerne Platzhalter in den Zellen speichern um anschließend Vergleiche durchführen zu können. (MySQL5)
> 
> Also z.B. hat die Spalte den Inhalt
> 
> ...



Hm, ist nicht verständlich was ich meine?

Trotzdem vielen Dank auch an dich.


----------



## planb2000 (11. Dezember 2008)

Hi,

dann evtl. so:


```
-- test tabelle
create table t_foo_test (
foo varchar(20)
)
-- insert testdaten
insert into t_foo_test values ('foo/bar')
insert into t_foo_test values ('bar/nicht/foo')
insert into t_foo_test values ('bar/foo/boo')
-- run for all
select * from t_foo_test
-- run for detection
select foo from t_foo_test
where INSTR(foo,'foo')
```

Hilft das ?

Grüße


----------



## versuch13 (11. Dezember 2008)

planb2000 hat gesagt.:


> Hilft das ?



Hi. Nein leider nicht. Ist mein Beispiel so schlecht verständlich? 

Ich möchte einen Platzhalter in der Spalte ablegen. Also zum Beispiel:

*"foo/%/bar"* % => Platzhalter

Nun möchte ich mit einem String (der von außen kommt und feststeht es handelt sich um elemente einer url) die Inhalte vergleichen.
Der String könnte jetzt zum Beispiel so aussehen: "foo/xyz/bar" (sollte einen Treffer ergeben)


----------



## planb2000 (12. Dezember 2008)

Hi,

also in der spalte füge ich diesen String ein:

```
insert into t_foo_test values ('foo/%/bar')
```

und jetzt suche mit RegularExpressions:


```
SELECT * 
from t_foo_test 
where foo REGEXP 'foo|blub|apa' ;
```

Das sind die Ergebnisse:
foo
foo/bar
bar/nicht/foo
bar/foo/boo
foo/%/bar

Das sollte es sein, oder ? ;-)

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


----------



## versuch13 (12. Dezember 2008)

planb2000 hat gesagt.:


> Das sollte es sein, oder ? ;-)



Nein, macht auch keinen Sinn  Trotzdem danke.


----------



## MArc (12. Dezember 2008)

versuch13 hat gesagt.:


> Ich möchte einen Platzhalter in der Spalte ablegen. Also zum Beispiel:
> *"foo/%/bar"* % => Platzhalter



Hi,

wieso machst  Du das nicht einfach?


```
SELECT * FROM test;
++++++++++
foo/%/bar

SELECT * FROM test
WHERE 'foo/wuff/bar' LIKE field1
+++++++++
foo/%/bar
```
bekomme in beiden Fällen den Treffer.
Ob Du das nun mit URLs machst oder mit was anderem ist gehopst wie gesprungen.

Ist das Problem also, dass es bei dir so *nicht* funktioniert?

Grüße,
MArc


----------



## versuch13 (12. Dezember 2008)

Na klar funktioniert es, genauso habe ich es doch in meinem ersten Post beschrieben 

Nur liefert dass dann auch Ergebnisse wie:

foo/%

aber nur 

foo/%/bar

soll getroffen werden.

Ist für Like ja auch typisch ist. Daher die Frage nach REGEXP.


Mein erster Beitrag beschreibt das Problem doch eigentlich recht deutlich.  Nichts anderes ist gefragt, trotzdem danke.


----------



## MArc (12. Dezember 2008)

Hey,
ok jetzt wird's klarer.

Hast du mal versuch einen "globales" schlußzeichen zu definieren`?
Zum Beispiel, dass du hingehst und sagst jede Spalte plus einem $
Bei den Strings "von außen" hängst du dann natürlich ebenfalls ein $ ans ende an
und schon haste dasProblem mit ungewollten Übereinstimmungen gelöst, oder?

So hatte ich das damals auch gelöst, als ich in der Datenbank definiert hatte, welche Links quasi
"gültig" inkl. wildcard (in dem fall % und _ ) sind und so dann verglichen - hatte ziemlich gut funktioniert.

Grüße,
MArc


----------



## versuch13 (12. Dezember 2008)

MArc hat gesagt.:


> Hast du mal versuch einen "globales" schlußzeichen zu definieren`?
> Zum Beispiel, dass du hingehst und sagst jede Spalte plus einem $
> Bei den Strings "von außen" hängst du dann natürlich ebenfalls ein $ ans ende an
> und schon haste dasProblem mit ungewollten Übereinstimmungen gelöst, oder?



Ja, genau diesen Gedankengang hatte ich auch und habe es auch versucht nur bin ich leider nicht zu einer Lösung gekommen.


----------



## MArc (12. Dezember 2008)

Jetzt wäre ein guter Zeitpunkt, um uns zu sagen, an welcher stelle die Lösung hakt.
Welche art von URLs können in deinem Fall DENN verglichen werden und geben eine ungewolltest Resultat zurück ?

Achja, Du kannst das LIKE natürlich durch REGEXP ersetzen, nur
müssen dann natürlich die expr. auf regexp angepasst werden.
Dann kannst wirklich genau definieren, wie wo welchee URL gültig ist ohne ausnahmen und einengung von LIKE.


```
SELECT * FROM foo;
++++++++
^foo/.*/bar$

SELECT * FROM `test` WHERE 'foo/sd/bar' REGEXP field1
++++++++
^foo/.*/bar$

SELECT * FROM `test` WHERE 'foo/sd' REGEXP field1
=> kein treffer
```

Ich denke das sollte die Lösung sein.

Grüße,
MArc


----------



## versuch13 (12. Dezember 2008)

MArc hat gesagt.:


> Jetzt wäre ein guter Zeitpunkt, um uns zu sagen, an welcher stelle die Lösung hakt.


Habe ich bereits im ersten Post gemacht  Wenn der Platzhalter sich mitten in einem String befindet 



MArc hat gesagt.:


> Welche art von URLs können in deinem Fall DENN verglichen werden und geben eine ungewolltest Resultat zurück ?


Das ist ja nicht wirklich wichtig oder? Ich möchte Spalten treffen wie im ersten Beispiel erwähnt. Es gibt also Strings mit Platzhaltern mitten im String, wie genau die aussehen wäre jetzt hier einfach zu viel, aber wie gesagt ist es auch unwichtig wie genau sie aussehen, wichtig ist nur der Platzhalter befindet sich mitten im String. 



MArc hat gesagt.:


> Achja, Du kannst das LIKE natürlich durch REGEXP ersetzen, nur
> müssen dann natürlich die expr. auf regexp angepasst werden.
> Dann kannst wirklich genau definieren, wie wo welchee URL gültig ist ohne ausnahmen und einengung von LIKE.
> 
> ...



Ja, nur wollte ich eigentlich keine regulären Ausdrücke in den Spalten ablegen sondern nur ein Zeichen als Platzhalter (bzw. gibt es die Datensätze in der Form eben schon), hm.. 

Mich hat jemand darauf hingewiesen das Drupal etwas ähnliches für das Routing nutzt und ich habe mal einen schnellen Blick darauf geworfen und dort scheint es  in der Tat so zu laufen, es wird auch ein % als Platzhalter abgelegt und auch teilweise mit in einem String. Nur blicke ich durch die Architektur von Drupal ansonsten nicht durch um mich zu den Queries vorzuschlagen. 

Sollte sonst noch jemand eine Idee haben, die es ermöglicht wirklich nur mit einem einzigen Platzhalter (%) zu arbeiten wäre ich sehr dankbar. 


Ist doch klar wo das Problem liegt oder? Nur nochmal zur Sicherheit: Bei der LIKE Abfrage aus meinem ersten Beispiel wird 
natürlich ab dem Platzhalter alles aktzeptiert. Sieht der Platzhalter so aus:

"foo/%/bar"

dann erzeugen 

foo/xyz
foo/bar
foo/yoo/boo

alle Treffer, aber nur 

foo/xyz/bar oder foo/boo/bar usw. sollten Treffer erzeugen. Eben wie in MArcs REGEXP Beispiel.


----------



## MArc (12. Dezember 2008)

versuch13 hat gesagt.:


> Ja, nur wollte ich eigentlich keine regulären Ausdrücke in den Spalten ablegen sondern nur ein Zeichen als Platzhalter (bzw. gibt es die Datensätze in der Form eben schon), hm..



Ach, da drückt der Schuh.
Also, wenn ich das nun richtig gerafft habe, dann hast Du in deinem Fall wohl nur 2 Möglichkeiten:
*) du änderst einfach die %/_-Platzhalter mit regexp aus und hast die volle Macht
oder
*) du verwendest die Variante mit dem Schlußzeichen und musst ggf abstriche machen.

Wenn Du mit der Überlegung kämpfst, nach dem WHERE als Bedinung auf *beiden* Seiten unterschiedlich Vergleichstechniken zu nutzen, wird das nicht funktionieren.
Zum einen Technisch nicht möglich und zum anderen sind die Daten eben
in, ich sag mal, LiKE-Form gespeichert und die hat eben Löcher, die man nicht
mit regexp stopfen kann (außer du detailierst die wildcard mit einem skript o.ä. - wie schon geschrieben)

Edit: Zu deinem Edit:
Das Problem kannst Du aber mit dem ersten Lösungsansatz(ein zeichen dranhängen) in Griff bekommen.

Grüße und  nacht,
MArc


----------



## versuch13 (12. Dezember 2008)

MArc hat gesagt.:


> Edit: Zu deinem Edit:
> Das Problem kannst Du aber mit dem ersten Lösungsansatz(ein zeichen dranhängen) in Griff bekommen.



Hey MArc. Ja? Das wäre super, nur weiß ich leider nicht genau was du meinst? Du meinst ich kann auch für die LIKE Variante ein Schlußzeichen bestimmen? Muss ich dazu auch die Datensätze ändern? Ich weiß leider nicht wie das möglich ist...


----------



## MArc (12. Dezember 2008)

Morgen,

also:
Zu deinem Edit nochmal - gestern hatte wohl mein Hirn bissle Probleme.

Wir haben folgende Strings, die verglichen werden:

```
foo/xyz
foo/bar
foo/yoo/boo
```

Wir haben folgenden Inhalt in meiner Tabelle:

```
SELECT * FROM test;
++++++++++++
foo/%/bar
```

Folgend sind meiner Ergebnisse:

```
SELECT * FROM `test` WHERE 'foo/asd' LIKE field1 => kein Treffer
SELECT * FROM `test` WHERE 'foo/bar' LIKE field1 => kein Treffer
SELECT * FROM `test` WHERE 'foo/yoo/boo' LIKE field1 => kein Treffer
SELECT * FROM `test` WHERE 'foo/blaa/bar' LIKE field1 => Treffer
```
Also, wie man erkennt, bekomme ich nur Treffer, wenn am Anfang 'foo/' und
am Ende '/bar' steht.

Wenn du aber in der Tabelle ´test´ ein Eintrag "foo/%" hast, dann ist klar, dass
dieser *immer* getroffen wird - das löst du auch nicht mit regexp - denn
das ist genauso ein eindeutiger Treffer wie einer, der ein bisschen, ich sag mal, "genauer" ist.

Noch etwas als Hinweis

```
SELECT * FROM `test` WHERE 'foo/yoo/bar' REGEXP CONCAT( '^',REPLACE(field1,'%', '.*'), '$')
```
Sowas geht natürlich auch - also musste deine Daten garnicht umschreiben, um
REGEXP zu benutzen, auch wenn das im zweifelsfall langsam ist (ich schätz bei > 100.000 einträge wirste es merken)
Ob das nun irgendwie zur Lösung deines Problems hilft, kann ich nicht beurteilen.
Weil, wie schon geschriebe, die Beispielstring, die du oben genannt hast, greifen bei mir nicht und so bekomme ich nur den Treffer, den ich will - außer, ja außer natürlich
Du hast in der Tabelle ein Wert, der als letztes Zeichen ein "%" hat - aber ist logisch.

Grüße und viel Glück,
MArc


----------



## versuch13 (12. Dezember 2008)

MArc hat gesagt.:


> Also, wie man erkennt, bekomme ich nur Treffer, wenn am Anfang 'foo/' und
> am Ende '/bar' steht.



Weil du eben nur den einen Datensatz in der Tabelle hast  Wie gesagt ich habe aber auch Datensätze die sich ähneln und am ende den Platzhalter haben, zum Beispiel also:

"foo/%"
"foo/%/bar"




MArc hat gesagt.:


> Wenn du aber in der Tabelle ´test´ ein Eintrag "foo/%" hast, dann ist klar, dass
> dieser *immer* getroffen wird - das löst du auch nicht mit regexp - denn
> das ist genauso ein eindeutiger Treffer wie einer, der ein bisschen, ich sag mal, "genauer" ist.



Siehe oben. Aber mit REGEXP kann man es schon lösen, nur eben nicht wenn die Daten wie momentan mit einem % als Platzhalter vorliegen.



MArc hat gesagt.:


> Noch etwas als Hinweis
> *sql Code: *
> 
> 
> ...



Ja, darüber habe ich auch schon nachgedacht und wahrscheinlich bleibt mir nichts anderes übrig


----------

