while - t sql loop query




我怎樣才能組裝SQL與面向對象的Perl? (6)

我目前負責一個似乎與數據庫非常親密的過程。 我的程序/腳本/框架的目標是從不同的數據源中統一。 使用一種依賴注入的形式,我的進程在一個很高的水平工作正常。 每種數據源類型的實現都隱藏在最新的業務抽像中。 大。 我的問題是兩個。

1)我有一段很長的段落(這是困擾我的長度),它在Perl空間中組裝一條SQL語句,將這些不同的數據源轉換為一個同類的結束格式。 所以SQL字符串總是取決於我正在使用的數據的類型。 WHERE子句依賴,FROM子句依賴,INSERT子句依賴,這一切都依賴於。 這是高度依賴性,這使我感到困惑。 我如何以面向對象的方式建模這個過程? MagicObject-> buildSQL? 這基本上就是我現在所擁有的,但是感覺代碼的所有部分都知道太多,所以它的長度。

2)如果我有一個函數可以執行某些操作(構建SQL?),我是否將整個業務對像傳入,然後在最後一刻把它們串聯起來? 還是我提前把它們串起來,只讓我的函數處理它所需要的東西,而不是渲染對象本身?

編輯 :雖然我不懷疑ORM的重要性,但我不相信我們還在ORM領域。 想像一下,美國,國家和小說聯賽的棒球數據都存儲在不同的格式中,並且具有不同程度的標準化。 閱讀這些數據源並把它們放在一個統一的,標準化的池中是我的工作。 我感覺在這些對像上執行的ORM空間發生在我的進程之後。 如果你願意的話,我是一個數據管理員。 基本上沒有業務對象尚未採取行動,因為我缺乏統一的資源庫。

編輯^ 2 :引起了我的注意,也許我沒有詳細描述問題空間。 這是一個例子。

想像一下,你必須建立一個美國所有罪犯的主數據庫。 貴公司的服務是銷售位於頂層的產品,並以乾淨統一的格式訪問這些數據。

這些數據由50個州公開提供,但格式大不相同。 有些是一個數據文件,沒有規範化。 其他是CSV格式的標準化表格。 有些是Excel文件。 有些是TSV。 有些記錄甚至提供了不完整的手動干預(其他手動創建的數據源)。

我的項目的目的是為50個州的每個州制定一個“驅動程序”,並確保過程的最終產品是一個完美的關係模型中的罪犯主數據庫。 一切正確,模式完美的形狀等


如果你想要一個ORM,但是你想從沒有直接的字符串操縱/連接的位組裝SQL,那麼看看Fey ,它可以做你想做的事情。

更新:亞里斯多德Pagaltzis的答案好多了。 他實際上給出了Fey看起來像什麼樣的例子,以及它如何提供幫助。


如果你不想處理ORM,我經常有這樣的代碼:

my (@columns,@tables,@wheres,@order_bys,@values);

... # Add value to those variables as needed, using push.
... # use ? for variables to be quoted

# Build SQL statement
my $sql = "select ".join(",",@columns).
    " from ".join(",",@tables).
    " where ".join(" and ",@wheres).
    " order by ".join(",",@order_bys);

my $sth = $dbh->prepare($sql);
$sth->execute(@values);

簡單,不需要ORM,非常可定制。 另外,我總是發現ORM對於我處理的數據量來說太重了,但這是另一個主題。


我想你正在描述動態SQL-在運行時以編程方式構建請求。 這是對象關係映射器(如LINQ to SQL和LLBLGenPro)的一個常見功能,僅舉幾例。 建設一個不是一件小事。

通常,ORM將SQL語言對象化。 您編寫了一種“SQL文檔對像模型(DOM)”,允許您以編程方式構建SQL查詢(例如,將其作為“請求”對象)。 然後在Request對像上設置屬性,如Column集合,Table集合和Join集合(這些只是一種方法的示例)。結果將是一個SQL請求字符串,作為Request對象的一個屬性公開。

您還必須使Request對象能夠讀取數據源的模式定義。 你提到你的WHERE子句是依賴於類型的。 因此,您的SQL彙編程序必須能夠讀取模式並適當地構建子句​​。

這可能是你的情況矯枉過正。 我認為根本的問題是,你是否絕對需要動態SQL查詢,還是有一個不太複雜的選項,可以滿足您的要求?


請不要寫你自己的ORM。 使用類似DBIx :: Class的東西。

所有你提到的這些問題都已經解決了,並且在數千個其他應用程序中測試了這個實現。 堅持寫你的應用程序,而不是重新實現庫。 您可能不會在您的應用程序中實際使用 DBIC,但您應該查看其實施方法; 特別是它如何遞增地構建ResultSets(不是結果集,而是延遲查詢)。


你想看看Fey 。 幾個月前我就開始使用這個工具了,而且由於年齡的原因,實施仍然有一些困難,但背後的想法是可靠的。 F.ex.,從手冊中稍作修改:

my $user = $schema->table( 'user' );
my $q = Fey::SQL
    ->new_select
    ->select( $user->columns( 'user_id', 'username' ) )
    ->from( $user );

現在你可以寫一個這樣的函數:

sub restrict_with_group {
    my ( $q, $table, @group_id ) = @_;
    my $group = $schema->table( 'group' )->alias;
    $q
        ->from( $table, $group )
        ->where( $group->column( 'group_id' ), 'IN', @group_id );
}

這將添加從usergroup以及WHERE條件的內部WHERE 。 瞧,你可以在主程序中寫下以下內容:

restrict_with_group( $q, $user, qw( 1 2 3 ) );

但是,這個restrict_with_group函數將適用於任何具有group表的外鍵的查詢! 要使用它,可以傳遞要限制的查詢和要應用限制的表,以及要限制的組ID。

最後你說$q->sql( $dbh ) ,然後返回一個SQL字符串,表示你在$q像中建立的查詢。

所以基本上Fey給了你原生SQL丟失的抽象能力。 您可以從查詢中提取可重用的方面,並將它們打包為單獨的函數。


在我看來,你可能需要考慮解決這個問題的方法。 您目前有多個數據源,您需要將其視為單個數據源。 那麼為什麼要把它們作為單獨的數據源?

根據數據更新的頻率(或查看性能,訪問頻率),您可以將數據組合到臨時數據源(如SQLite)中。 如果來自每個狀態的數據都有一個翻譯器,它將從格式A到SQLite表格中的通用格式,那麼您可以使用您選擇的方法來訪問它。

這種方法還允許靈活性,因為您的數據訪問需求可能會改變。 例如,如果您被問及“每個州有多少金發司機超速票”? SQLite數據庫可以用一個命令完成,而其他解決方案可能需要返回一組數據,然後需要解析,分組和設置輸出。







oop