2009-02-04 122 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。使用正确的工具来完成正确的工作。