Firebird 2.5.2 にテーブルがあります。
create table SearchTest ( val varchar(20) )
次の 2 つの行があります。
insert into SearchTest ( val ) values ('one')
insert into SearchTest ( val ) values ('three')
列「val」に「one」または「hre」が含まれるすべての行を選択したいと考えています。linq を使用すると、次のように表現できます。
var a = from b in TestEntities.SEARCHTESTs
from c in new []{ "one", "hre" }
where b.VAL.Contains(c)
select b;
これにより、次のようなクエリが生成されます。
SELECT
"C"."VAL" AS "VAL"
FROM "SEARCHTEST" AS "C"
CROSS JOIN (SELECT
_UTF8 X'4F4E45' AS "C1"
FROM ( SELECT 1 AS X FROM RDB$DATABASE) AS "D"
UNION ALL
SELECT
_UTF8 X'485245' AS "C1"
FROM ( SELECT 1 AS X FROM RDB$DATABASE) AS "E") AS "F"
WHERE ((POSITION("F"."C1", "C"."VAL")) > 0)
ただし、検査を簡単にするために、これは同じことを行います。
SELECT
val,
substr,
POSITION(Substr, Val) as pos
FROM
SearchTest
CROSS JOIN
(
SELECT 'one' AS substr FROM RDB$DATABASE
UNION ALL
SELECT 'hre' AS substr FROM RDB$DATABASE
)
「one」と「hre」という検索語を使用すると、予想どおりの結果が得られます。
val substr pos
--- ------ ---
one one 1
three one 0
one hre 0
three hre 2
ただし、検索語の長さが一致しない場合:
SELECT
val,
substr,
POSITION(Substr, Val) as pos
FROM
SearchTest
CROSS JOIN
(
SELECT 'one' AS substr FROM RDB$DATABASE
UNION ALL
SELECT 'hree' AS substr FROM RDB$DATABASE
)
一致は失敗します:
val substr pos
--- ------ ---
one one 1
three one 0
one hree 0
three hree 0
検索語をキャストすると (ここに示すように、キャスト タイプが一致する必要はありません):
SELECT
val,
substr,
POSITION(Substr, Val) as pos
FROM
SearchTest
CROSS JOIN
(
SELECT cast('one' as varchar(3)) AS substr FROM RDB$DATABASE
UNION ALL
SELECT cast('hree' as char(5)) AS substr FROM RDB$DATABASE
)
一致は再び機能します。
val substr pos
--- ------ ---
one one 1
three one 0
one hree 0
three hree 2
これはなぜですか。また、それを回避する方法はありますか?
編集:
Jiri Cincura は、このバグは次のリリースで修正されていると述べています。文字列定数は明示的に varchar に変換されるようになりました。Firebird トラッカーの問題: http://tracker.firebirdsql.org/browse/DNET-466