Kyralessa What is your most useful sql trick to avoid writing more sql?.提出了这个问题。我从最后一个问题中得到了很多好主意,我有兴趣看看这个问题是什么。
再一次,我没有保持这个问题的声誉。我等了7天,寻找答案,然后将其标记为维基。问题所获得的声誉,对这个问题有好处。
基本规则:
虽然编写代码,将处理从SQL转移到代码以解决性能问题当然是合理的,但这实际上不是问题的关键。问题不仅限于绩效问题。目标不仅仅是减少sql来完成工作。
传达这个概念,以便其他用户说“哦,哇,我不知道你能做到这一点。”
示例代码非常有用,可以帮助那些主要是视觉学习者的人。
明确说明您正在使用的语言,以及您正在使用的SQL方言。
把自己放在读者的鞋子里。他们需要在他们面前的屏幕上看到什么,这将导致顿悟。你的答案是为了让读者受益。为他们写下来。
非现场链接,如果它们出现在示例后面。非现场链接作为真实答案的替代品不是。
对于我没有想过的读者,可能还有其他一些东西可以让它变得更好。获得创意。分享知识。玩得开心。
[编辑] - 看起来好像有一段时间没有任何活动。 5票= 50,所以有赏金,并且已被证实。
答案 0 :(得分:10)
如果你想避免写SQL,可以使用ORM,例如nHibernate,或者一个Microsoft产品Linq to SQL / Entity Framework
这比使用生成器更好,因为您不需要重新运行生成器,如果使用Fluent nHibernate,您可以通过约定启用配置,甚至不维护映射文件/类。
答案 1 :(得分:2)
从INFORMATION_SCHEMA
中的元数据生成SQL SP,视图等。然后可以使用自定义代码扩充代码生成。
如果许多SP会做类似的事情,为了便于单点维护,我将生成动态SQL。
所有这些都会导致更少的SQL代码,更多的代码被重复使用,并且经过更好的测试 - 就像任何库一样。
答案 2 :(得分: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连接到db,构建SQL,执行它,实例化新对象,填充它们并将它们发回。完成更改对象后,只需调用
即可SQL.Write(customer);
将所有更改的项目更新回数据库 - 请注意,仅更改的项目以及仅更改的列。
添加了奖励:它支持SQL Server,Oracle,Informix。客户端代码永远不必改变。
答案 3 :(得分:2)
我在PHP for MySQL中推出了自己的ORL(对象关系映射器)。它真正简化了与更改数据库有关的所有事情,并且在非常简单的情况下非常有效。
它包含一个可以继承的基类。您可以轻松地将其子类化:
<?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免费的)。由于它注意到字段的数据类型,因此参数化查询很简单。
当然,它不能做我需要的一切,但它节省了大量的开发时间和代码。
答案 4 :(得分:1)
在我工作的地方,我们做了几件事来减少SQL并减少在Java中使用SQL的相关开销。 (我们使用MSSQL,MySQL和Oracle运行Java)。
最有用的技巧是使用Java的setObject方法来绑定参数。这与Varargs结合使用,可以编写用于执行SQL的实用程序方法:
DBUtil.execSQL(Connection con, String sql, Object... params)
简单地遍历参数并使用statement.setObject(index,param [index-1])。对于null,您使用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,而不是盲目地重新编写相同的语句。
答案 5 :(得分:1)
在我的一个项目中,我使用了一个元模型(表,列,关系),它将信息添加到内置的sys *视图中。
我的元模型中的部分数据用于生成插入/更新/删除的日志记录触发器,以及在替换删除触发器中实现级联删除。约。 100个表格为这些触发器生成的代码大约是12.000行TSQL代码。
SP生成一个C#数据结构,将实时数据库模式与我的开发数据库模式进行比较,以确保升级正常。
最近,元模型甚至允许我在基于FormView的Asp.Net表单中生成用于删除验证的C#代码(即,如果存在依赖记录,则无法删除记录)。
答案 6 :(得分:0)
我建议创建专注于任务的共享方法,并使用简单的SQL元素,而不必编写sql。我使用Subsonic来访问MS SQL的数据。但是,您可以将其设置为非特定于数据库,例如DAL。这些示例可以自定义为ORM,但是您可以访问数据。我建议创建一个静态类,将其缩小到特定任务。
例如,如果你有一个数据网格来填充,你知道一个视图,表,存储过程来填充它,创建一个类似于下面的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语句,你想要出现什么以及如何在select中,以及whereclause和你绑定。
BindDataGridViewWhere(dgvCars,“tbl_Cars”,“CarName”,“Color,mdl as Model”,“Color ='blue'”);
这适用于您进行大量绑定的任何对象,例如dropdownboxes,listboxes,datagridviews,其他任何东西。然后,对于不适合此模型的其他人,请使用仅返回数据集的方法。这样,如果您需要在显示它之前与它进行交互,您可以执行其他业务逻辑等。
我喜欢这种方法,因为如果你想切换数据框架,你有一个地方可以做出改变。你可以用这种方式快速建立一个屏幕。
答案 7 :(得分:0)
我使用了outlet-orm这是一个不会生成的令人敬畏的ORM解决方案。我想我过去所做的所有技巧都是迄今为止最方便省时的。
答案 8 :(得分:0)
如果您可以使用python环境,我强烈推荐使用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
答案 9 :(得分:0)
使用内置的.NET功能,例如Expression Columns(显示的是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()
答案 10 :(得分:0)
SQL没有任何问题。使用正确的工具来完成正确的工作。