【问题标题】:Why is SQL text-based?为什么 SQL 是基于文本的?
【发布时间】:2014-01-21 02:29:22
【问题描述】:

我想这不是特别“适合我们的问答形式”,但不知道在哪里可以问它。

为什么 SQL 查询是基于 text 的?是有历史动机,还是只是懒惰?

mysqli_query("SELECT * FROM users WHERE Name=$name");

它会引发大量类似上述的愚蠢错误,鼓励 SQL 注入。对于 SQL,它基本上是 exec,而 exec'ing 代码,尤其是动态生成的,被广泛劝阻。 另外,老实说,准备好的语句似乎只是一种冗长的解决方法。

为什么我们不采用一种更面向对象、不可注入的方式来做这件事,比如拥有一个具有某些方法的可直接访问的数据库对象:

$DB->setDB("mysite");
$table='users';
$col='username';
$DB->selectWhereEquals($table,$col,$name);

数据库本身本机实现的,完全消除了与exec的所有相似之处,并使SQL注入的整个基础无效。

在真正的问题上达到高潮,是否有任何数据库框架可以做这样的事情?

【问题讨论】:

  • 从历史上看,所有的语言都是基于文本的......现在你可以设计其他方法,但在那个时候这是唯一可行的选择。
  • “是否有任何数据库框架可以做这样的事情” - 是的。有很多

标签: sql exec sql-injection object-oriented-database


【解决方案1】:

为什么编程语言是基于文本的?很简单:因为文本可用于表示强大的人类可读/可编辑的 DSL (Domain-specific language),例如 SQL。

更好的 (?) 问题是:为什么程序员拒绝使用占位符?

现代数据库提供程序(例如 ADO.NET、PDO)支持占位符和适当范围的数据库适配器1。未能利用这种支持的程序员只能怪自己。

除了直接数据库提供程序中对占位符的普遍支持之外,还有许多可用的不同 API,包括:

  • “流利的数据库”;这些通常将 AST(例如 LINQ)映射到动态生成的 SQL 查询上,并处理诸如正确使用占位符之类的细节。
  • 各种各样的ORMs;可能包含也可能不包含流式 API。
  • Android SQLite API 中的原始 CRUD 包装器,看起来与提案非常相似。

喜欢 SQL 的强大功能,并且我编写的查询几乎没有一个可以用这样一个微不足道的 API 来表达。即使是强大的提供程序 LINQ,有时也会妨碍我(尽管谨慎使用 Views 会有所帮助)。


1 尽管 SQL 是基于文本的(并且用于将查询的 shape 传递到后端),但不需要包含绑定数据in-line,这就是 SQL 注入问题(能够更改查询的 形状)出现的地方。数据库适配器可以并且如果它足够聪明,可以使用公开的 API由目标数据库。对于 SQL Server,这相当于 [通过 RPC] 单独发送数据,对于 SQLite,这意味着创建和绑定单独的预处理语句对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-28
    • 2011-02-24
    • 2017-01-27
    • 2017-09-02
    • 2016-09-16
    • 2011-02-12
    • 2021-06-09
    • 1970-01-01
    相关资源
    最近更新 更多