8

オブジェクト指向ビルダーDSLを介してSQLを構築することと、生のSQL文字列をパラメーター化することの利点を理解しようとしています。同じクエリを3つの方法で調査/実装した後、生のSQLがはるかに読みやすいことに気付きました。これは、「なぜフープを飛び越えるのか」という疑問を投げかけます。生のSQLを宣言して使用しないのはなぜですか?

これが私が思いついたものです:

まず、アダプターを使用する任意のDBで使用できるため、SQLの移植性が向上すると思います。これが大物だと思いますよね?それでも、ほとんどのT-SQLはほとんどのデータベースで理解できませんか?

次に、他のクエリ、名前付きスコープのチェーンなどの基礎として再利用できるクエリオブジェクトを提供します。

SQLを宣言するのではなく構築することで実現する主な投資収益率はどれくらいですか?

def instances_of_sql(ttype_id) #raw sql
  ttype_id = get(ttype_id).try(:id)
  ti   = get('tmdm:type-instance')
  inst = get('tmdm:instance')
  type = get('tmdm:type')

  self.class.send :sanitize_sql, [%{
    SELECT t.*
    FROM associations a
    JOIN roles type    ON type.association_id = a.id AND type.ttype_id = ?
    JOIN roles inst    ON inst.association_id = a.id AND inst.ttype_id = ?
    JOIN topics t      ON t.id = inst.topic_id
    WHERE a.topic_map_id IN (?)
    AND a.ttype_id    = ?
    AND type.topic_id = ?
  }, type.id, inst.id, self.ids, ti.id, ttype_id]
end

def instances_of_sql(ttype_id) #sequel
  ttype_id = get(ttype_id).try(:id)
  ti = get('tmdm:type-instance')
  ir = get('tmdm:instance')
  tr = get('tmdm:type')

  DB.from(:associations.as(:a)).
    join(:roles.as(:tr), :tr__association_id => :a__id, :tr__ttype_id => tr[:id]).
    join(:roles.as(:ir), :ir__association_id => :a__id, :ir__ttype_id => ir[:id]).
    join(:topics.as(:t), :t__id => :ir__topic_id).
    where(:a__topic_map_id => self.ids).
    where(:a__ttype_id => ti[:id]).
    where(:tr__topic_id => ttype_id).
    select(:t.*).sql
end

def instances_of_sql(ttype_id) #arel
  ttype_id = get(ttype_id).try(:id)
  ti   = get('tmdm:type-instance')
  inst = get('tmdm:instance')
  type = get('tmdm:type')

  #tables
  t    = Topic.arel_table
  a    = Association.arel_table
  tr   = Role.arel_table
  ir   = tr.alias

  a.
    join(tr).on(tr[:association_id].eq(a[:id]),tr[:ttype_id].eq(type[:id])).
    join(ir).on(ir[:association_id].eq(a[:id]),ir[:ttype_id].eq(inst[:id])).
    join(t).on(t[:id].eq(ir[:topic_id])).
    where(a[:topic_map_id].in(self.ids)).
    where(a[:ttype_id].eq(ti[:id])).
    where(tr[:topic_id].eq(ttype_id)).
    project('topics.*').to_sql
end

名前付きスコープに心から感謝し、それらを連鎖させることがいかに有益であるかを理解しています。モデルを介して関連レコードにアクセスすることについては心配していません。私は純粋に複雑なクエリを構築することについて話している。

4

2 に答える 2

8

@KyleHeironimusがNickKallenのArelに関する考えに与えたリンクには、次の行があります。

副選択で派生テーブルが使用されていることに注意してください。私の意見では、これはひどいです。これを書く方法を知っているのは高度なSQLプログラマーだけです(私は就職の面接でこの質問をよくしますが、誰もがそれを正しく理解しているのを見たことがありません)。そして、それは難しいことではありません!

さて、Kallenは、これをSQLの構成下でのクロージャーの欠如に帰します。それは場合によっては真実かもしれませんが、私の経験ははるかに乱暴です-ほとんどの開発者はSQLでひどいです。彼らは最も基本的なことしか知りません。これらの基本的なことは、セットベースの言語で手続き型ソリューションを検索しようとするときに誤用されます。私が所属していたある会社でデータベースが3NFにあることの利点について、他のすべての開発者と一緒に議論しなければなりませんでした。才能のある人(ほとんどは:)ですが、SQLやデータベースについての手がかりはありません。

それをC#またはRubyまたはPython <選択した言語を挿入>に入れると、開発者は再び満足します。彼らは手続き的/OOの考え方に固執し、彼らに似合うコードを作成することができます。

私はこれが私に投票を獲得しないことを知っています、おそらくまったく反対ですが、それは私の見解です。ところで、アレルは面白そうだ。


上記のコメントの補足として、6か月以上にわたって、その間にSequelライブラリを頻繁に使用してきたことは、本当に美しいことだと言えます。今では、それをに使用したいと思います。ストレートSQLを使用します。信じられないほど強力で、頭を悩ませることなくシンプルで高度なことを実行できるだけでなく(常にいくつかあります)、使用したSQLを出力できます。また、SQLにドロップダウンすることもできます。私がする必要があると感じます。

これは、ほとんどの開発者のSQLの理解についての私のコメントを無効にするものではありません(最近、他の人と話をする開発者から、正規化はストレージスペースが高価だった時代の遺物であると言われました...ああ!)Sequelライブラリの開発は、データベースを本当に理解している人によって明らかに行われているというだけです。SQLやデータベース設計などを知っているなら、それはあなたにもっと速くより多くの力を与えます。私が使用した他のORMと同じことを言うことはできませんが、おそらく他の人は違った考え方をするでしょう。

于 2011-02-10T20:17:58.537 に答える
4

あなたはすでにその理由にかなりの打撃を与えています。

これがArelの作成者からの考えです。

于 2011-02-10T19:57:58.290 に答える