web-dev-qa-db-ja.com

SQLクエリビルダーを使用する利点は何ですか?

生のSQLを使用するのではなく、クエリビルダーを使用する利点はありますか?

例えば。

$q->select('*')
  ->from('posts')
  ->innerJoin('terms', 'post_id')
  ->where(...)

対:

SELECT * FROM posts WHERE ...

多くのフレームワークがこの種の抽象化レイヤーを使用しているようですが、その利点を理解できていません。

18
Anna K.

フレームワークを介してSQLを作成することの抽象化は、抽象的です。

手作業でSQLを書くこと自体はそれほど悪いことではありませんが、エスケープとサニタイズの問題が発生し始め、これは混乱に変わります。抽象化レイヤーは、これらすべてをバックグラウンドで処理し、コードをクリーンにして、多数のmysql_real_escape_string()呼び出しなどをなくすことができます。

さらに、これはSQLの異なる方言を説明する可能性をもたらします。すべてのデータベースが同じように構築されているわけではなく、キーワードや特定の機能の構文が異なる場合があります。抽象化レイヤーを使用すると、バリアントの正しい構文を動的に生成することができます。

抽象化レイヤーはパフォーマンスに影響を与える可能性がありますが、一般に、返されるコードのクリーンさと堅牢性に比べれば無視できます。

20
user7007

クエリビルダーは私の嫌いなので、使用しないように独自のフレームワーク(Apeel)を作成しました。

PDOを使用している場合は(間違いなくお勧めします)、入力のサンタイズが処理されます。

他の人が言ったように、データベース間の切り替えが簡単になりますが、「最低公分母」機能をサポートする傾向があり、より高度な機能をサポートしないか、パフォーマンスが低下します。

私は1986年頃からデータベースを使用したシステムを開発してきましたが、その間ずっと、パフォーマンスを向上させる必要がある場合を除いて、使用するデータベースを実際に変更している会社に遭遇することはめったにありません。パフォーマンスを向上させるためにデータベースを変更する場合は、簡単にするためにクエリビルダーを使用するのではなく、新しいデータベースを最大限に活用するためにクエリを手動で最適化して時間を費やす方がはるかに理にかなっています。

クエリビルダーのqwirksを把握するために費やした時間(その後、より優れたものに切り替えたときに再学習)は、SQLを最適化する方法の学習にはるかに生産的に費やされます。

とにかく、それを使わないのはそのためですが、愛する人もいます。

11

理論的には?はい。 Glenn Nelsonが指摘しました 彼らがしばしばあなたをどのように助けるか。 (それが良いクエリビルダーである場合)。

実際には?常に理論に準拠しているわけではなく、実際に問題を引き起こす可能性があります。いくつかの一般的なDBMSに対してクエリビルダーを使用していて、すべてが適切であるとします。次に、顧客から、選択したクエリビルダーが処理できないいくつかの癖があるDBMSにアクセスするように求められます。 (この問題は、古いバージョンのPervasiveで作業する必要があったときに発生しました。)

だが!絶対にすべきことは、データアクセスレイヤーを分離し、必要に応じて新しいレイヤーに交換できることを確認することです。そうすれば、すべての機能を備えたクールなクエリビルダーを使用できますが、問題のDBに奇妙な疑似SQLを使用する新しいクエリビルダーをプラグインする必要がある場合は、.

4
ElGringoGrande

クエリビルダーの実用的な日常のメリットは、コードの再利用とDRYの原則に従う能力です。

クエリビルダーを使用すると、SQLの繰り返し部分をメソッドに入れることができます。次に、これらのメソッドを使用して複雑なSQLを作成します。たとえば、次のようになります。再利用可能なJOIN句:

function joinTaskWithClient($queryBuilder) {
    $queryBuilder->join('task', 'contract', 'task.contract_id = contract.id')
                 ->join('contract', 'client', 'contract.client_id = client.id');
}

したがって、使用法は次のようになります。

$queryBuilder->select('client.name')
             ->from('client')
             ->where('task.id=:task')->setParameter('task', 42);
joinTaskWithClient($queryBuilder);

お気付きかもしれませんが、クエリビルダーを使用すると、SQL文字列を手動で収集する場合とは対照的に、SQLの一部を任意の順序で追加できます(たとえば、WHEREの後にJOINを追加できます)。また、その目的と利点を確認するには、 ビルダーパターン を参照してください。

エスケープとサニタイズについては同意しますが、これはクエリビルダーなしでも実現できます。 DBタイプ/方言の抽象化に関して-これは非常に理論的で疑わしい利点であり、実際にはほとんど使用されていません。

3
GerKirill

私のカスタムSQLビルダーのreadmeファイルに基づいて回答を提供します( Dialect

(プレーンテキストが続き、ライブラリ固有の参照が削除されました)

要件

  1. 複数のDBベンダーをサポート(例:MySQL、PostgreSQL、SQLite、MS SQL/SQL Server、Oracle、DB2など)
  2. 新しいDBに簡単に拡張できます(実装に依存しない構成設定が望ましい)
  3. モジュール性と実装に依存しない転送可能性
  4. 柔軟で直感的なAPI

特徴

  1. 文法ベースのテンプレート
  2. カスタムソフトビューのサポート
  3. dbの抽象化、モジュール性、転送可能性
  4. 用意されたテンプレート
  5. データエスケープ

上記の機能と要件は、SQL抽象化ビルダーを使用する理由を示しています

上記の機能のほとんどは、ほとんどのSQLビルダーでサポートされています(私の知る限り、リストされているすべてがサポートされているとは思いませんが)

使用例:

  1. 複数のDBベンダーと(基礎となるコードを変更せずに)動作するCMSプラットフォーム
  2. DBベンダーが変更しやすいカスタムアプリケーションコードおよび/またはdBスキーマが動的である(つまり、多くのクエリはハードコード化できないが、十分に抽象化してコードを変更に対して堅牢にする必要がある)
  3. 本番環境で使用されているものとは別のDBを使用したプロトタイピング(少なくとも一部のコードでは、重複するコードベースが必要になります)
  4. アプリケーションコードは、特定のDBプロバイダーや実装に(密接に結合していない)(同じDBベンダー内、たとえば異なるバージョンのDBベンダー内でも)、したがって、より堅牢で柔軟性があり、モジュール式です。
  5. クエリとデータエスケープの多くの通常のケースはフレームワーク自体によって処理され、通常これは最適で高速です

最後に、私が持っていたユースケースの例。基になるDBスキーマ(ワードプレス)が、実行する必要があるデータクエリのタイプに適していなかったアプリケーションに加えて、一部のWPテーブル(例:投稿))が持っていたアプリケーションを構築していた(したがって、すべてのアプリケーションデータに対して完全に新しいテーブルを用意することはできませんでした)。

その場合、カスタム/動的条件によってモデルをクエリできるMVCのようなアプリケーションを作成できるため、クエリのハードコーディングはほとんど悪夢のようになりました。結合を使用して最大2〜3個のテーブルのクエリをサポートし、条件をフィルタリングして、どのテーブルを何に結合するかを確認し、必要なエイリアスなども処理する必要があるとします。

明らかにこれはクエリ抽象化のユースケースであり、さらに、カスタムソフトビューを定義する機能が必要(または少なくとも大きなメリット)(結合テーブルの集合体としてモデルに適した1つのカスタムテーブルの場合)。次に、それははるかに簡単で、よりクリーンで、モジュール式で、柔軟性がありました。別の側面では、アプリケーション(コード)は(dbスキーマ)正規化ツールとしてクエリ抽象化レイヤーも使用しました。一部の人が言うように、それは将来の保証でした。

明日、人々が追加のオプションやデータが必要だと判断した場合、それを数行でモデルに追加して問題なく動作させることは非常に簡単です。さらに、明日、人々がwordpressをもう使用しないことを決定した場合(アプリケーションがwordpressにプラグインとして疎結合されているため))、それはまた、新しいスキーマに適応するために、数行のコードでモデルを(定義の)変更するのも比較的簡単です。

どういう意味ですか?

2
Nikos M.

多くの場合、これらのクエリの引数の一部は、実際には定数ではなく値です。現在、それらの多くは基本的にユーザーフォームの投稿から派生しています。したがって、SQLインジェクション攻撃には多くの可能性があります。したがって、本質的にクエリの形成には完全な検証が必要です。

さて、これは私たちが開発者を信頼していないと言っているわけではありませんが、クエリの形成は簡単かもしれませんが、可能なすべての検証チェックをどこでも繰り返すと、偶然見逃したり、クエリを変更したりしても、クエリを変更せずに、検証チェックを更新しません。一部の初心者は、これを見逃すことのすべての危険性さえ知っているかもしれません。したがって、クエリビルダーの抽象化は非常に重要です。

1
Dipan Mehta

クエリビルダーは、内部でSQLを生成しながらテーブルを選択してグラフィカルに結合できるGUIアプリだと思っていましたが、今ではクエリビルダーを、純粋なSQLクエリを作成する必要がない方法を提供するAPIと呼ぶことも理解しています、SQLフレーバーの潜在的な違いを抽象化します。

このようなクエリビルダーを使用するのは良いことですですが、それらに大きく依存している人はDBAに尋ねない傾向があると思う傾向があります:「ねえ、これは私が頻繁に使用するクエリです。 」.

誤解しないでください。

テーブルではなくビューに対してクエリを作成する必要があると思います。セキュリティやフィルタリングのためではありませんが、これらは正当な理由ですが、同じ理由から、具体的なクラスではなくインターフェイスに対してコーディングする必要があります。ビューは「契約」のようなもので、インターフェースがOOPで「契約」であるのと同じ方法です。基礎となるテーブルを変更できますが、ビューがプログラマに同じ「契約」を強制的に表示する限り、コードは壊れません。

繰り返しますが、誤解しないでください。クエリビルダーを使用してビューにクエリを実行できますが、多くのビューはクエリを記述してDBAに尋ねる結果として生じるプロセスとして存在するようになります。「これを作成してください」 。

クエリを記述しないと、特定のビューを作成する必要性を検出できないと思うのは間違っていますか?

私が懸念しているもう1つのことは、初心者プログラマーがSQLを習得していないことです。SQLは、人が作成した最も美しいテクノロジーの1つであり、そうする必要がないためです。

0