7

ディレクトリ パスを含む SQLite テーブルにクエリを実行して、階層下のすべてのパスを検索したいと考えています。列の内容の例を次に示します。

/alpha/papa/
/alpha/papa/tango/
/alpha/quebec/
/bravo/papa/
/bravo/papa/uniform/
/charlie/quebec/tango/

の下のすべてを検索すると、次の/bravo/papa/ものが得られます。

/bravo/papa/
/bravo/papa/uniform/

私は現在、このようにしようとしています(より単純な方法を使用できない理由については、以下の長い話を参照してください):

SELECT * FROM Files WHERE Path >= '/bravo/papa/' AND Path < '/bravo/papa0';

これは機能します。少し奇妙に見えますが、この例ではうまくいきます。'0' は '/' より 1 大きい Unicode コード ポイントです。辞書式に並べると、「/bravo/papa/」で始まるすべてのパスは、それより大きいか「bravo/papa0」より小さいかを比較します。ただし、私のテストでは、これを試すとこれがうまくいかないことがわかりました。

SELECT * FROM Files WHERE Path >= '/' AND Path < '0';

これは結果を返しませんが、すべての行を返す必要があります。私が知る限り、問題は SQLite が「0」を文字列ではなく数値として扱っていることです。たとえば、'0' の代わりに '0Z' を使用すると、結果は得られますが、誤検知のリスクが生じます。(たとえば、実際にエントリ「0」があった場合。)

私の質問の簡単なバージョンは次のとおりです。そのようなクエリで「0」をユニコード文字「0」を含む長さ1の文字列として扱うようにSQLiteを取得する方法はありますか(「!」、「*」などの文字列をソートする必要があります' および '/' を、'1'、'=' および 'A' の前に) 整数 0 の代わりに (SQLite はすべての文字列の前にソートします)?

この場合、すべてのエントリは常に「/」で始まるため、「/」の下のすべてを特別に検索することで実際に回避できると思いますが、この種のことを回避する方法を本当に知りたいです一般に、これは Javascript の「==」演算子とまったく同じように不愉快なほど驚くべきことです。

最初のアプローチ

より自然なアプローチは、LIKE または GLOB 演算子を使用することです。例えば:

SELECT * FROM Files WHERE Path LIKE @prefix || '%';

しかし、すべての有効なパス文字をサポートしたいので、'_' と '%' 記号には ESCAPE を使用する必要があります。どうやらこれにより、SQLite が Path でインデックスを使用できなくなります。( http://www.sqlite.org/optoverview.html#like_optを参照してください) 私は本当にここでインデックスの恩恵を受けたいと思っています。ディレクトリ名には特殊文字が含まれ、POSIX では NUL と '/' 以外、GLOB の '*' と '?' も使用できます。文字。

コンテキストのためにこれを提供しています。根本的な問題を解決するための他のアプローチに興味がありますが、SQLite の数字のように見える文字列のあいまいさに直接対処する回答を受け入れたいと思います。

類似の質問

sqlite が文字列を数式として評価しないようにするにはどうすればよいですか?

その質問では、値は引用されていませんでした。値が引用符で囲まれている場合やパラメーターとして渡されている場合でも、これらの結果が得られます。


編集- 以下の私の答えを見てください。列は、SQLite が NUMERIC として扱った無効な型「STRING」で作成されました。

4

1 に答える 1

6

*うなり声*。列は誤って「TEXT」ではなく「STRING」と指定されていたため、NUMERIC アフィニティがありました。SQLite は型名を認識しなかったため、NUMERIC にしました。SQLite は列型を強制しないため、数値のような文字列がその列に挿入されるたびに変換されることを除いて、他のすべては期待どおりに機能しました。数値型。

于 2013-03-14T09:14:15.023 に答える