我的sql问题:
> sql本质上是不安全的:sql是一种用于插入的语言,没有任何方法可以防止插入代码而不是数据.防止插入的唯一方法是将sql与使用它的应用程序完全隔离.为什么还没有在sql中解决呢?
> sql似乎已经为其中包含的数据的最小存储大小做了.虽然这对大量数据仍然有很大的意义,但它对于较小的数据库不再是真的吗?
> sql强制所有内容都适合二维关系模型,具有特定的关系表来执行其他维度.对我来说这是两个问题:
>数据的一致性完全依赖关系表
>数据在人类失败的情况下很难理解
> sql不保留历史记录,因为默认情况下它具有破坏性的更新:当然,创建历史记录的方式有各种各样的方法,但是需要使用额外的表格和使用时间戳的自定义书写的东西,或者写一个新的记录对于每一个变化,导致表格规模增长.
> sql似乎更倾向于丢失数据丢失一致性:如果发生错误或一致性丢失,将情况恢复到一致状态的唯一方法是使用备份,这意味着最新的更改将被破坏.这部分是因为缺乏历史(见4),而且由于缺乏人的可读性,没有真正的方法让人尝试纠正错误.
>特别是在Web环境中,使用sql通常意味着经常有不止一次地创建模型.在正常(简单)PHP Web应用程序中两次:一次在PHP中,一次在sql中.在一个完整的堆栈Web应用程序三次:一次在客户端应用程序,一次在中间件,一次在sql数据库(如果没有使用ORM).由于不同的编程语言和它们之间的类型差异,这意味着这些模型之间存在很多可能的冲突.我知道ORM如ActiveRecord和Django至少解决了这些问题的一部分,但还需要额外的工作量,因为sql表包含VARCHAR(25),并且没有使用任何语言(JavaScript,Ruby,PHP,Perl,Python等)知道那种结构是巨大的.
>数据结构变化似乎被视为一致性问题:如果数据结构发生变化,表格更改将应用于该表中的每个现有记录,即使记录最初没有该字段,以及是否生成感觉该记录有这个领域.一组这些更改导致自动迁移,这增加了另一层可能的问题,特别是在一致性方面.
>混合存储逻辑和应用程序逻辑:sql似乎渴望将部分应用程序逻辑作为存储过程(CouchDB也通过视图执行).
虽然我明白,对于某些类型的操作,您需要服务器端和非常严格的控制程序,我不明白为什么它们存储在数据库中,而作为存储引擎的一部分,而不是应用程序的一部分中间件).
我知道(但不是很熟悉)Postgresql Hstore这样的东西,但是我完全不知道如何解决上面提到的事情.
感谢任何见解!
解决方法
我想你是指SQL Injections这是最危险的安全漏洞之一.
然而,sql注入主要是教育的问题,因为大多数教科书和课程根本不解释bind parameters.当人类直接使用数据库时,将文字值写入sql语句本身就适用于即席查询,但在程序中只是简单的错误方式.程序应始终使用绑定参数(非常少的性能异常),有效地保护程序100%免受sql注入.问题是sql教科书没有这样说.
否则,sql具有可靠的安全系统,允许您基于某些规则(“行级安全性”)限制对表,视图以及有时甚至选择的行的访问.
>“最小存储大小可能”
对不起,我没有得到这个问题.
>关于规范化.
你是对的.规范化解决了一些问题(重复数据删除和防止无意的不一致),但打开了其他一些问题.即:
>如何从多个表轻松访问数据.
>如何保持多个表的一致性.
>如何应对有意的“不一致”aka.历史(主数据变化)
原则上,sql应该提供工具来补偿正常化引起的这些挑战.
应该使用连接和sql的类似操作来访问来自许多表的数据. sql不仅仅是以1:1的方式存储和检索数据,它提供工具(联接,子查询,集合操作…),以将归一化数据转换为最适合特定任务的形式.这是在运行时有意做的,因为任务不需要事先知道.另一方面,数据的性质被认为是静态的,因此将其存储为归一化方式是有效的.这是关系模型和sql的一个非常重要的关键概念:数据的性质不会改变,所以它应该是持久的.如何使用这些数据变化很大,并且经常会随着时间的推移而变化 – 因此,这必须是动态的.这当然是一个非常规则的任务,所以有一个坚实的工具使其变得容易.我们称这个工具sql;)DRY规则可以通过使用视图或CTEs来实现,但是两者都可能会损害性能,因为实现没有被很好地优化(我公开批评!).
在多个表中保持数据一致性大多是在约束的帮助下完成的.
SQL:2011终止了处理意图的“不一致”(历史):这将允许“AS OF”查询,并提供保持时间一致性的工具(例如,一行的有效性可能与另一行的有效性不重叠).可以说,相当糟糕的是,花了40年左右的时间才提出了一个解决办法.而且我甚至不知道这是什么时候常用的!
我认为这一点对于每个系统来说都是非常真实的:“数据在人类失败的情况下很难理解”(我的重点).但是,我认为您可能意味着很难调查问题,因为所需的数据可能会分散在多个表中. sql的答案是:基本上只是存储查询的VIEW.但是,根据数据库带VIEW可能会引入性能问题.然而,这是一些数据库频段的限制,而不是sql或关系模型的限制.
>保持历史
以上我已经提到过(sql:2011).
每个想要保留历史的系统也是如此:“导致指数级增长的表格大小”.虽然我会说它“不断增长”不是“指数级”.
应对这些工具是触发器或ORM.如果你想确定没有人做“破坏性的更新”,你可以撤销该表上的UPDATE权限(也可以在保存方面删除DELETE).
>“更喜欢数据丢失失去一致性:”
我发现一个有趣的观点.但是,sql的答案是,您首先尝试非常难以将错误的数据导入系统.主要通过使用适当的模式,约束ACID.以这种方式,您的声明是正确的:而不是接受不一致的数据被拒绝(这是不同于丢失的东西!).因此,您必须在有人输入拒绝的数据时处理错误,而不是稍后您尝试解决不一致的原因,因为您首先接受了错误的数据.所以是的,这是关系模型和sql的哲学!
缺乏人的可读性显然取决于你的背景.但是,使用sql的正确性是相当不错的,我想说.在这里,我也想引用原来的IBM文章,关于SEQUEL(当时是真正的名字):
SEQUEL is intended as a data base sublanguage for both the professional programmer and the more infrequent data base user.
在我的观察中,这是绝对真实的:我最近有一个任务来教sql来支持员工,以便他们直接在数据库中调查案例.他们不是程序员,而是很快了解sql.我认为这里踢你的“人”论点:他们有什么问题是导航一个包含几百个表的真实世界的关系模型.但是,通过要求开发为涉及多个表的一些常见任务提供意见,很快解决了这个问题.然后加入这些观点就没有问题了.
对于关系思维,你需要一个不同的思维方式,你需要一个不同的中间集功能编程.这不是好还是坏 – 但对你而言可能不常见.一旦你经常使用它,你会习惯它.
>对象/关系阻抗不匹配
我认为这个话题不需要任何长时间的讨论:是的,它存在,是的,有工具以某种方式来处理它.我在我的文章中提到过度使用我的观点.
>数据结构变化
我认为这主要是由于对关系模式的了解不佳.比较如下:“数据的性质”
这也是一个非常好的讨论参数:模式与“架构少”.选择你的味道“模式少”通常意味着“不提供模式管理工具”,但是您必须应对事实,即我们有时希望向现有实体添加更多属性. RDBMS为此提供了工具:新列可以为空或具有默认值.可以使用CREATE AS SELECT来进行更大的更改,例如将一个属性移动到一个额外的表(例如1:n).您甚至可以提供一个兼容性视图,它仍然可以传递数据,就像移动的属性仍然存储在表中一样.一旦您更改了架构,您的应用程序就可以依赖于它的约束(例如列的存在或约束的有效性).数据库可以非常可靠的方式为您做的很多事情.你不需要在你的应用程序中关心的东西.
您没有提到的一个争论是,这些架构更改通常涉及停机时间.对于过去,在某种程度上也是如此,这是肯定的.例如. MysqL最近在5.6中引入了ALTER TABLE.然而,这通常是实现限制,而不是固有地关系到关系模型或sql的问题.甚至一些更复杂的更改(如将属性移动到另一个表)可以在完成权限并仔细计划时在线完成(我已经用昂贵的数据库之一完成了所需的所有工具).一般来说,将迁移代码保留在应用程序之外,并使用它来处理数据库.在迁移之后,您不应该在数据库中或应用程序代码中都有迁移工件.当然,有些情况下,停机时间是不可避免的(我认为).
>“混合存储逻辑和应用逻辑”
没有人强迫你使用存储过程.我个人也认为存储过程被过度使用,主要是因为存储过程存储在数据库中,因此可以由可能无法访问其他源代码的数据库管理员进行更改(优化).换句话说:我认为这绝对是绝望的.
第二个参数当然是过度使用ORMs和不允许在应用程序中使用真实sql的策略.