2009-02-04 126 views
7

這個問題被Kyralessa建議於What is your most useful sql trick to avoid writing more sql?.我有很多好主意想去嘗試最後一個問題,我很想看看這個問題出現了什麼。你用什麼編碼技巧避免編寫更多的sql?

再一次,我沒有保持這個問題的聲譽。我在等待7天,找到答案,然後將其標記爲wiki。這個問題所贏得的聲譽爲這個問題帶來了豐厚的回報。

基本規則:

  • 雖然這肯定是合理的編寫代碼,從SQL移動處理到代碼解決性能問題,這是真的不是問題的地步。問題不僅限於性能問題。爲了完成這項工作,我們的目標不僅僅是減少sql。

  • 溝通的概念,讓其他用戶說:「哦,哇,我不知道你可以做到這一點。」

  • 示例代碼非常有用,可以幫助那些主要是視覺學習者。

  • 明確聲明您正在使用哪種語言以及您正在使用哪種SQL語言。

  • 把自己放在你的讀者的鞋子。他們需要在他們面前的屏幕上看到什麼,那會導致頓悟。你的答案是讓讀者受益。寫給他們。

  • 非現場鏈接是好的,如果它們出現在示例之後。非現場鏈接作爲真實答案的替代品並非如此。

有可能還有其他的事情讓讀者更好,我沒有想到。獲得創意。分享知識。玩得開心。

[編輯] - 看起來好像有一段時間沒有任何活動。 5票= 50,所以有獎金,它已經wikified。

+0

+1,因爲它現在是-1,我真的不明白這一點。這是一個有效的問題。 – hmcclungiii 2009-02-04 17:25:21

+0

我知道我已經回答了這個問題,但現在我正在閱讀一個鏈接:這個問題和鏈接之間有什麼區別。編碼技巧編寫更少的SQL和SQL技巧來編寫更少的代碼?沒關係。 – 2009-02-04 17:30:18

回答

1

我在哪裏工作,我們已經做了幾件事情,以減少SQL和減少使用Java中的SQL的相關開銷。 (我們使用MSSQL,MySQL和Oracle運行Java)。

最有用的技巧是使用Java的setObject方法綁定參數。這與可變參數相結合,讓你寫用於執行SQL一個實用方法:

DBUtil.execSQL(Connection con, String sql, Object... params) 

過來的參數簡單地迭代,並使用statement.setObject(索引,PARAM [指數-1])。對於你使用setNull()的空值。我們使用getResultSet方法擴展了查詢的這個概念;包裝的ResultSet對象也會關閉其語句,從而更容易進行資源管理。

爲了減少實際的SQL代碼寫的,我們有一個查詢建設框架,可以讓你指定了一堆列及其類型,然後使用這個自動指定搜索條件和輸出列。我們可以輕鬆指定連接和連接標準,並處理大部分正常情況。好處是您可以生成大約10行代碼的報告,包括不同的查詢參數,排序,分組等。代碼太複雜,不能包含在這裏。

我還使用Oracle的ALL_TABLES和ALL_TAB_COLUMNS表生成SELECT語句;我用另一種技巧是使用ResultSetMetadata來分析表:

ResultSet rs = DBUtil.getResultSet(con, "SELECT * FROM " + someTable); 
ResultSetMetaData rsm = rs.getMetaData(); 

boolean first = true; 
for (int i = 1; i <= rsm.getColumnCount(); i++) { 
    String col = rsm.getColumnName(i).toUpperCase(); 
    // do something with the column name 
} 

這使得很容易產生某些類型的報表;在這種情況下,我們有一個活動表和一個存檔表,我們將記錄從一個移動到另一個。沒有深入討論關於使用歸檔表的問題,我編寫的Java代碼允許我修改這兩個表,而無需修改歸檔腳本。

我們使用的另一個技巧是使用常量爲我們所有的表和列名。這使得輸入SQL有點乏味,但它允許我們(除其他外)輕鬆地爲具有相似或相同構造的表生成SQL。由於我們使用常量來定義列名,因此代碼實際上會強制相同的列具有相同的名稱。使用常量還可以查找對特定列的引用,從而允許您檢查可能與正在進行的工作相關的其他SQL語句。這讓我們可以從其他模塊重用SQL,而不是盲目地重新編寫相同的語句。

2

INFORMATION_SCHEMA的元數據中生成SQL SP,視圖等。該代碼生成可以通過自定義代碼進行擴充。

如果許多SP會做類似的事情,爲了便於單點維護,我將生成動態SQL。

所有這些事情導致更少的SQL代碼和更多的代碼被重用,並且更好地測試 - 就像任何庫一樣。

Here's an example of code generation to avoid writing SQL

10

如果你想避免書面方式的SQL使用ORM如NHibernate的,或者微軟的產品之一的LINQ to SQL /實體框架

這甚至更好,然後用一臺發電機,因爲你贏了不需要重新運行生成器,並且如果使用Fluent nHibernate,則可以啓用「通過約定配置」,甚至不需要維護映射文件/類。

2

語言:C#/ VB.NET。

我現在可以寫一個數據庫備份系統,而無需編寫任何SQL可言。我的DAL使用POJO的類定義來即時生成SQL。示例:

SearchCriteria sc = new SearchCriteria(); 
sc.AddBinding("Customer_id", "ALFKI"); 
List<Entity> customers = SQL.Read(sc, new Customers()); 

上面的代碼將返回與Customer_id匹配的Customer實例列表爲「ALFKI」。 DAL連接到數據庫,構建SQL,執行它,實例化新對象,填充它們並將它們發送回去。當您完成更改對象,只需撥打

SQL.Write(customer); 

有所有改變的項目更新回到分貝 - 提個醒,只有改變,只是改變了列的人。

附加獎金:它支持SQL Server,Oracle,Informix。客戶端代碼永遠不需要改變。

0

我建議創建專注於任務的共享方法,並使用簡單的SQL元素,而不必編寫sql。我使用Subsonic爲我的數據訪問MS SQL。但是,您可以使其與數據庫無關,例如DAL。這些示例可以針對ORM進行定製,或者您可以訪問數據。我建議創建一個靜態類,把它縮小到一個特定的任務。

舉例來說,如果你有一個DataGrid來填充,你知道一個視圖,表,存儲過程從填充它,創建一個類似於下面的C#代碼的函數:

public static void BindDataGridViewWhere(DataGridView dgv, string tablename, string selectList, string whereClause) 
{ 
    Query qQuery = new Query(tablename); 
    qQuery.SelectList = selectList; 
    qQuery.WHERE(whereClause); 
    DataSet dsDGV = qQuery.ExecuteDataSet(); 
    dgv.DataSource = dsDGV.Tables[0]; 
    dgv.RowHeadersVisible = false; 
} 

然後,在頁面init或類似的東西,簡單的1行調用這個方法將datagridview傳入where語句,你想要顯示什麼以及如何選擇,以及where子句和你綁定的地方。

BindDataGridViewWhere(dgvCars,「tbl_Cars」,「CarName」,「Color,mdl as Model」,「Color ='blue'」);

這對你做很多綁定的任何對象很有用,比如dropdownboxes,listboxes,datagridviews,其他任何東西。然後,對於不適合此模型的其他人,請擁有一個只返回數據集的方法。這樣,如果您需要在顯示它之前與它進行交互,則可以執行其他業務邏輯等。

我喜歡這種方法,因爲如果你想切換數據框架,你有1個地方做出改變。您可以通過這種方式快速構建屏幕。

0

我已經使用outlet-orm這是一個非常棒的ORM解決方案,不會生成。我認爲,在過去我所做的所有技巧中,這是迄今爲止最方便和節省時間的技巧。

0

如果可以使用python環境,我會強烈推薦SQLAlchemy。

我嘗試的另一件事是編寫我自己的模式生成器來測試我們的系統在工作中。這更多的是生成不同的查詢組合來嘗試崩潰系統。基本上,我定義了一個僞deparse樹,字典和列表

SQLAlchemy

這裏的代碼片段

>>>for row in session.query(User, User.name).all(): 
... print row.User, row.name 
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password FROM users [] 
<User('ed','Ed Jones', 'f8s7ccs')> ed 
<User('wendy','Wendy Williams', 'foobar')> wendy 
<User('mary','Mary Contrary', 'xxg527')> mary 
<User('fred','Fred Flinstone', 'blah')> fred 
2

我推出我自己的ORL(對象關係映射器)在PHP MySQL的。它真正簡化了與更改數據庫有關的所有事情,並且它適用於簡單情況。

它由一個可繼承的基類組成。您可以輕鬆進行子類化:

<?php 
class CSomething extends CDatabaseObject 
{ 

} 

// create a new Something 
$oSomething = new CSomething(); 
$oSomething->somevariable = 'blah'; 
$oSomething->Save(); 

// fetch an old Something by primary key 
$oSomething = new CSomething(1); 
// .. and delete it 
$oSomething->Delete(); 
?> 

它會自動計算表中的索引和主鍵。如果需要的話,你當然可以告訴班上這些事情,如果它做的不好。

您可以通過指定SQL的WHERE子句來進行基本搜索(因此它不完全是SQL免費的)。由於它關於字段的數據類型,參數化查詢很簡單。

當然,它不能做我需要的一切,但它節省了大量的開發時間和代碼。

1

在我的一個項目中,我使用了一個元模型(表,列,關係),它將信息添加到內置的sys *視圖中。

我的元模型中的部分數據用於生成插入/更新/刪除的日誌記錄觸發器,並在替代刪除觸發器中實現級聯刪除。約。100個表格爲這些觸發器生成的代碼約爲12.000行TSQL代碼。

SP生成一個C#數據結構,它將實時數據庫模式與我的開發數據庫模式進行比較,以確保升級正常。

最近,元模型甚至允許我在基於FormView的Asp.Net窗體中生成用於刪除驗證的C#代碼(即不能刪除記錄,如果依賴記錄存在的話)。

0

使用內置的.NET功能,如表達式中的列(如圖所示VB例子) 將數據綁定多個列在一次顯示:

ds.Tables(0).Columns.Add(
    New DataColumn("CustomDescription", GetType(String), 
        "LastName + ', ' + FirstName + ' - ' + 
        WorkEmail")) 
ResultsListBox.DataSource = ds 
ResultsListBox.DataTextField = "CustomDescription" 
ResultsListBox.DataValueField = "EmployeeID" 
ResultsListBox.DataBind() 
0

沒有什麼錯SQL。使用正確的工具來完成正確的工作。