LIKE の勉強中に、納得できないことがあり悩んでます。
psql で以下のような操作を行いました。
最後の DELETE コマンドは、
%から始まる str を持つ行を削除したかったのですが、
全ての行が削除されてしまいます。
%から始まる str を持つ行を削除するには、
この方法は誤りですか?
それとも PostgreSQL のバグですか?
test=> CREATE TABLE tbl_name ( str CHAR(8) );
CREATE TABLE
test=> INSERT INTO tbl_name VALUES ( 'abc' );
INSERT 17056 1
test=> INSERT INTO tbl_name VALUES ( '%z' );
INSERT 17057 1
test=> INSERT INTO tbl_name VALUES ( 'xyz' );
INSERT 17058 1
test=> SELECT * FROM tbl_name;
str
----------
abc
%z
xyz
(3 rows)
test=> DELETE FROM tbl_name WHERE str LIKE '\%%';
DELETE 3
-- K.Yamamoto
> test=> SELECT * FROM tbl_name;
> str
> ----------
> abc
> %z
> xyz
> (3 rows)
hoge=> select * from tbl_name where str like '\\%%';
str
----------
%z
(1 row)
バックスラッシュは 2 つ要る様です。
http://www.postgresql.jp/document/pg734doc/user/functions-matching.html#FUNCTIONS-LIKE
| リテラルのアンダースコアやパーセント記号を他の文字のマッチングに
| 使用するのではなくそのものをマッチさせたい場合には、pattern の中の
| それぞれのアンダースコアとパーセント記号はエスケープ文字でエスケープ
| されなければなりません。デフォルトのエスケープ文字は逆スラッシュですが、
:
| リテラル文字列において逆スラッシュには始めから特別な意味合いがあるので
| 逆スラッシュを含んだパターン定数を記述するときは問い合わせの中で 2 つの
| 逆スラッシュを記述する必要があることに注意してください。 したがって、
--
持田 修司 NETside Technologies Inc.
-- Equal Opportunity for All Good Architectures, NetBSD. --
> バックスラッシュは 2 つ要る様です。
>
> http://www.postgresql.jp/document/pg734doc/user/functions-matching.html#FUNCTIONS-LIKE
>
> | リテラルのアンダースコアやパーセント記号を他の文字のマッチングに
> | 使用するのではなくそのものをマッチさせたい場合には、pattern の中の
> | それぞれのアンダースコアとパーセント記号はエスケープ文字でエスケープ
> | されなければなりません。デフォルトのエスケープ文字は逆スラッシュですが、
> :
>
> | リテラル文字列において逆スラッシュには始めから特別な意味合いがあるので
> | 逆スラッシュを含んだパターン定数を記述するときは問い合わせの中で 2 つの
> | 逆スラッシュを記述する必要があることに注意してください。 したがって、
なるほど。
news:bkmnkd$m4u$1...@caraway.media.kyoto-u.ac.jp に記した事例では、
\ を2つ記述すればうまく行くと言う事が分かりました。
上述した URI の記事の事例に戻りますが、
LIKE '\%%' は、
'\%%' を LIKE の処理に移す前にサーバー自体が \ を解釈してしまい、
実際 LIKE にパターンが渡されるときには、
'%%' となってしまったため全ての行が削除されてしまった。
そのため、上述したURIの記事に示したとおりの動作をさせたい場合は、
LIKE に '\%%' がうまく渡るように、最初の \ をエスケープする必要がある。
と言う解釈であってますかね?
-- K.Yamamoto
>> | リテラル文字列において逆スラッシュには始めから特別な意味合いがあるので
> LIKE に '\%%' がうまく渡るように、最初の \ をエスケープする必要がある。
>
> と言う解釈であってますかね?
1.1.2.1 文字列定数 のところに、「C 言語形式のバックスラッシュによる
エスケープも有効」.. という部分があり、\b, \f, \n, \r, \t,
8 進数 \xxx で文字指定とかできるそうなので、それの関係なのではないで
しょうか。
news:bko41k$eou$1...@caraway.media.kyoto-u.ac.jp に記した内容と
ほぼ同じですが、LIKE についてまとめてみました。
LIKE で % から始まる文字列を導き出すには、
「LIKE 自身に '\%%' と認識させなくてはならない」
そのため LIKE '\%%' と言う記述だと、
\% をエスケープされた「ただの % 」と認識してしまい、
LIKE に '%%' と評価されてしまう。
そのため LIKE に '\%%' と認識させるには、
LIKE '\\%%' と記述し \ もエスケープする必要がある。
( _ も同様)
上記の事柄を踏まえ、
文字 \ から始まる文字列を LIKE によって導き出すには、
LIKE '\\\\%' と悲惨な状況になるが、こうするしかない。
= 演算子等と違って、LIKE も演算子と言う割には、
あとで取って付けたような印象を持ちました。
SQLの学習を進めていけば、
これらの理由も分かるようになるかもしれないと信じ、
がんばりたいと思います。
フォローアップしてくださった持田さんには感謝してます。
ありがとうございました。
-- K.Yamamoto
> 文字 \ から始まる文字列を LIKE によって導き出すには、
> LIKE '\\\\%' と悲惨な状況になるが、こうするしかない。
# スクリプト内で組み立てるとさらに倍とか。(笑)
もう一度引用します、
| リテラル文字列において逆スラッシュには始めから特別な意味合いがあるので
| 逆スラッシュを含んだパターン定数を記述するときは問い合わせの中で 2 つの
推測ですが、「リテラル文字列」として一度解釈され、さらにその後
「パターン定数」として解釈される、という実装になっていると思われます。
> = 演算子等と違って、LIKE も演算子と言う割には、
> あとで取って付けたような印象を持ちました。
そのとおりで、「取って付けた」ということかと。
PostgreSQL 固有の都合だと思います。
fj.comp.databasesの記事<bkoge5$ks4$1...@caraway.media.kyoto-u.ac.jp>で
nos...@excite.co.jpさんは書きました。
> 文字 \ から始まる文字列を LIKE によって導き出すには、
> LIKE '\\\\%' と悲惨な状況になるが、こうするしかない。
20年くらい前のCommunications of ACMに掲載されてい
たThe Telnet Songという歌を思い出してしまいました。
There is a program called telnet to get to another
CPU...という歌詞で始まるやつです。書いたのは斯界で
名の知られたGuy L. Steele Jr.。
telnetというコマンドは当時からあったのですが、なん
せインターネットなど存在しないころの話なので、接続
先に指定できるのは隣接するホストだけ。遠くのホスト
につなぐにはtelnetでとなりのホストに入り、そこから
また別のホストにtelnetし、そこからさらに別のホスト
に...という具合でした。
telnetのエスケープ文字は^^(Control-Uparrow)、接続
終了コマンドはqだったので、自ホストから隣接ホスト
へのtelnetは^^-qで終了できましたが、隣接ホストから
そのとなりへのtelnetを終了するには^^-^^-q、さらに
そのとなりのときは^^-^^-^^-^^-qといった具合にタイ
プする必要があったわけですね。
で、The Telnet Songは、1番はControl-Uparrow Qで終
わるけど、2番はControl-Uparrow Control-Uparrow Q、
3番はControl-Uparrow Control-Uparrow Control-
Uparrow Control-Uparrow Qといった具合で、n番の歌詞
はControl-Uparrowを2^(n-1)回くり返したあとにQで終
わるようになっていたわけです。歌詞が何番まであった
か憶えていないのですが、先に進むに従ってエンディン
グがだんだん伸びてきて、知らずに聞いた人はそのうち
げらげら笑い出すことになるというしかけ。
本題に戻ってエスケープの\をいくつ連続して書くかで
すが、私はCで書いたMakefile生成プログラムで\を8個
並べて書いた記憶があります。(^^;
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp