DLookup などの省略形のドメイン関数は魅力的ですが、欠点もあります。同等の Jet SQL は次のようなものです
SELECT FIRST(island)
FROM villages
WHERE village = ?;
一致する候補が複数ある場合は、「最初」の候補が選択されます。「最初」の定義は実装 (SQL エンジン) に依存し、Jet/ACE エンジン IIRC では未定義です。どちらが最初になるか知っていますか?そうでない場合は、DLookupを避けてください:)
[興味深いことに、Jet/ACE の答えは、データベース ファイルが最後に圧縮されたときのクラスタ化インデックスに基づく最小値か、データベースが圧縮されていない場合は最初の (有効な時間) 挿入値のいずれかになります。クラスター化されたインデックスは、存在する場合は PRIAMRY KEY によって決定されます。それ以外の場合は、UNIQUE 制約または NOT NULL 列に定義されたインデックスです。それ以外の場合は、最初の (有効な時間) 挿入された行です。NOT NULL 列に複数の UNIQUE 制約またはインデックスが定義されている場合、クラスタリングに使用されるのはどれでしょうか? わからない!方法を知っていても、「最初」を判断するのは簡単ではないという考えを理解していただけると思います!]
また、最適化の観点からドメイン集約関数の使用を避けるようにという Microsoft のアドバイスも見ました。
Access データベースのクエリ パフォーマンスに関する情報
http://support.microsoft.com/kb/209126
「DLookup 関数などのドメイン集計関数の使用は避けてください... Jet データベース エンジンは、ドメイン集計関数を使用するクエリを最適化できません」
クエリを使用して書き直すことを選択した場合は、PARAMETERS 構文を利用できます。または、Jet 4.0/ACE PROCEDURE 構文を使用することもできます。
CREATE PROCEDURE GetUniqueIslandName
(
:village_name VARCHAR(60)
)
AS
SELECT V1.island_name
FROM Villages AS V1
WHERE V1.village_name = :village_name
AND EXISTS
(
SELECT V2.village_name
FROM Villages AS V2
WHERE V2.village_name = V1.village_name
GROUP
BY V2.village_name
HAVING COUNT(*) = 1
);
このようにして、エンジン自体の機能 (または少なくともそのデータ プロバイダーの機能) を使用して、必要に応じてすべての文字 (二重引用符と単一引用符だけでなく) をエスケープできます。