模块化SQL?(2007)

2020-06-18 15:39:05

(对不起,这可能有点跑题。但我认为这与PL设计有关。)。

SQL功能强大。它是陈述性的。复杂的数据访问算法可以非常简洁地表示出来。但是它的语法是单一的。一条SQL语句跨越多个表(或者说OOA&;D中的域对象)。当我检查工作中的许多SQL语句时,它们中的许多都有相似的模式:某些内部联接或WHERE子句在许多地方重复,以实现相同的过滤规则。我找不到一种简单的方法来抽象出这些模式,重用语句的片段。(就像Mixin或Character?)。我找不到一种简单的方法来分解复杂的SQL或以可管理的方式从较小的构建块中组合复杂的SQL语句。

从OOP的角度来看,数据访问应该隐藏在OR层中,并且所有操作都应该通过域对象上的方法来完成。但这在许多应用中是不可行的。我公司开发的软件实现的许多业务流程都是面向批处理的,它们已经需要数小时才能运行。如果我坚持让所有东西都通过OR层,并剥夺优化SQL的功能,那么软件就根本无法使用。

还有其他选择吗?还有,有没有关于模块化SQL或功能与SQL一样强大的模块化数据访问语言的研究?(我在谷歌上找不到很多东西。)。

2007年09月05日23:16|陆上交通大学论坛|上一论坛话题|下一论坛话题|其他博客|21426阅读量。

选择显示注释的首选方式,然后单击保存设置以激活您的更改。

你的分析已经比大多数人做得更深入了。从历史上看,路易斯安那州立大学对这个特定的问题并不太感兴趣,尽管对我来说,它似乎已经足够切题了。但它对另一个论坛Usenet group(Usenet Group)最感兴趣。Usenet group&34;comp.database ases.design&34;。我要警告你,那个论坛没有这个论坛那么精致,虽然技术内容也不错。(把路易斯安那州立大学想象成一家英国男性俱乐部,会员们坐在高背椅上讨论巴贝奇的最新作品,歹徒在门口被拒之门外,而comp.database理论则是一家狂野的西部沙龙,如果你走进酒吧时不向吧台后面的科德总统的肖像致敬,就会有一把椅子砸过你的头顶。)。

我个人的看法是:问题出在O/R围栏的两边。正如您所说,R&34;语言(SQL)是整体式的。无论是C++、Java,还是其他语言,都缺乏合适的类型系统来处理SQL擅长的这类问题。具体地说,名义类型不适合处理任意连接。这只是一个总结;当然还有更多的问题。

假设您有两个表,每个表有10列。连接这两个表的查询可以选择二十列中的任何子集。即使我们假设大多数连接都包括一个外键,这仍然为我们提供了19列集合的能力集。大约50万种不同的组合中的每一种都是不同的关系类型。显然,给它们起不同的名字是令人望而却步的。这不仅仅是即席查询的问题;客户端代码中任何位置选择不同列集的每个查询都将有其自己的类型。

关系模型的优点之一是能够准确地将您当前需要的数据(和数据类型)组合在一起;只需满足类型系统,就不需要额外的东西了。

为了抽象出SQL中的常见模式,必须有一种方法来抽象表、联接等上的查询。函数式语言通过抽象高阶函数来支持这种常见模式分解,但SQL不支持高阶查询,因此文本重复是不可避免的。

为了抽象出SQL中的常见模式,必须有一种方法来抽象表、连接等上的查询。

好的,我会咬人的。为什么视图不能算作抽象?您可以在其他查询中使用它,而无需重复查询文本。

我质疑这种方法是否有助于解决实践中发现的问题。至少在您的示例中,在我看来,出现这种情况完全是因为SQL语法乱七八糟之后进行了语法抽象清理。

至少在您的示例中,在我看来,出现这种情况完全是因为SQL语法乱七八糟之后进行了语法抽象清理。

语法抽象有自己的语义(重写)。这个示例也许可以通过宏展开来实现,或者表和字段标签可能是底层语言中的一流值,而底层语言的功能要强大得多。

我认为如果处理得当,数据库中的这种抽象在实践中可能非常有用。目前没有预打包的抽象SQL查询的市场,但这可能只是因为SQL提供的抽象和重用工具很少。如果您可以将模式和查询打包,以便与现有数据库进行简单集成,或许市场就会出现。想象一下,将预打包的库存管理数据库+抽象查询与预打包的销售前端混合在一起。

事实上,我们正从相反的方向看到这一趋势:将数据库和搜索集成到已经支持抽象的语言中(参见:OZ、LINQ等)。那么,为什么不将抽象和重用集成到数据库中,使其成为一种合适的语言呢?

在本例中,答案是肯定的。我不是在为它辩护,我只是想解释裸露是什么意思。这个想法可能在某个地方潜藏着更大的力量。

例如,假设查询和行确实是一阶的,并且这些T和R变量可以存储在表中,您可以这样做:

这将把SQL带入函数式语言领域。当然,性能影响可能相当大。

..。假设..。这些T和R变量可以存储在一个表中。

以一阶逻辑为基础的关系代数有一些优势,这样的特性将把这种基础抛在脑后。

以一阶逻辑为基础的关系代数有一些优势,这样的特性将把这种基础抛在脑后。

我不假思索地浏览了去功能化文件的前几个部分。作者说,整个程序中的所有函数都可以枚举。是真的吗?函数可以动态构造吗?我在想,如果作为参数传递给高阶辅助函数的函数是动态构造的,去函数化是否仍然有效。

这取决于您所说的动态构造是什么意思。如果您可以枚举程序中动态创建函数的所有静态位置(即,如果您可以找到";lambda&34;的所有实例),那么您就可以使用去功能化,即使这些位置有许多不同的动态路径,即使它们被调用了无限次。具体地说,您可以对代码使用去功能化,如下所示:

(定义(加法器x)(λ(Y)(+x y)(定义L1(映射(生成加法器5)';(1 2 3 45)(定义L2(映射(λ(X)(+x 5))';(1 2 3 45))。

去功能化通常是整个程序的转换,所以您需要找到所有的lambda。然而,我认为可能有一些技巧可以使去功能化更加模块化。

但是,如果另一方面,当您说动态构造时,您指的是代码的动态加载,或者字节码(或机器代码等)的动态生成,或者可能使用类eval的元编程,那么您可能是对的,即去功能化是不会起作用的。

但是,如果另一方面,当您说动态构造时,您指的是代码的动态加载,或者字节码(或机器代码等)的动态生成,或者可能使用类eval的元编程,那么您可能是对的,即去功能化是不会起作用的。

我认为它也可以在那里工作,但是运行时去功能化已经有了一个名字:多态内联缓存。

至于将高阶结构擦除为SQL的一阶语言,我相信这是可能的,因为所有存储的结构都是一阶的,并且在运行查询(触发器、存储过程和查询本身)时整个程序都是系统已知的。这种去功能化会比数据库查询规划者已经做的更复杂吗?

等效的是返回TABLE的UDF(用户定义函数),遗憾的是,不同的RDBMS在存储过程和UDF中是不同的。

我在谷歌上搜索了这个词,但什么也没找到。令我惊讶的是,在这一领域竟然没有任何积极的研究。

嗯.。创建一个嵌入在Haskell之类支持高阶查询的类似SQL的DSL,并使函数求值为一个普通的SQL字符串,然后将其传递给普通的RDB,这样做有意义吗?

正如其他人所说,高阶函数会有所帮助。然而,我认为通常与关系代数相关的更多数学语法也使事情更清晰。它涵盖的内容与SQL大致相同,但由更简单、更正交的运算符组成。

(我之所以说大体上是";是因为最后的列名是";Employees.FirstName&34;和";Departments.Building";而不是";FirstName&34;和";Building";。可以通过重命名操作修复此问题。)。

我对SQL的印象一直是它的目标是模仿关系演算,而不是关系代数。当然,不同之处在于声明性和过程性-微积分术语只说明结果必须满足哪些属性,而代数术语规定了获得结果的具体方法(因此,与形成外部接口的SQL查询相比,更类似于RDBMS内部使用的查询计划)。

同样的批评也适用于OP:SQL的目的不是表达算法,而是表达需求,从需求中可以或多或少地推断出或多或少合理的算法,显然在过程中使用关于数据物理组织的内部知识。

因此,可能缺少的是抽象部分声明性需求(我相信在某些逻辑中是谓词)的方法。

由此还可以得出结论,视图并不是(对于这个问题)真正的解决方案,因为它们属于另一个概念级别(更接近代数)。

..。微积分项只是说明结果必须满足哪些性质,而代数项则规定了获得结果的具体方法。

关于这句话,我已经听过很多次了,但我脑子里想不出来。我读过各种比较和约束代数和微积分的论文,但在我看来,它们看起来几乎完全一样。我在代数中看不到丝毫的过程性。你能帮我理解一下你的意思吗?或许可以举个例子?

由此还可以得出结论,视图并不是(对于这个问题)真正的解决方案,因为它们属于另一个概念级别(更接近代数)。

我也不明白这句话。视图只是一个可被视为基本关系的命名查询。在我看来,我们是否更接近代数似乎是查询语言的一个属性,与系统是否支持命名查询无关。

这是因为没有,关系代数和微积分都只是一阶逻辑方言,具有完全相同的表达能力。

它只是对RA操作员执行某些操作的不同心理图景或解释,而不是被视为将一个域映射到另一个域的功能。这种心理图景在数据库优化器设计和实现中很有用,在数据库优化器设计和实现中,原始查询被表示为一组RA运算符,这些运算符实际上是用金属实现的,例如散列连接。

这种表示对于优化过程本身也是非常有用的,在优化过程中,原始的RA运算符被等价的运算符替换,并以各种方式置换,简单地说,以创建最优的执行计划,这是非常不可能的或部分可能的,但是对于没有在任何类型的代数上闭合的网络查询语言来说是非常困难的,从而排除了RA类型的代数变换!

关系代数是一种函数式语言,由许多关于关系的高阶运算组成。因此,关系代数+λ抽象将是另一种选择的自然理论基础。

但从更实际的角度来看,如果您坚持使用SQL,最好的做法是实现一种中间语言,您的应用程序将使用该语言来生成SQL。对于这种语言,您将实现一个SQL查询字符串生成器后端,以及一组允许您将中间语言查询组合成更复杂查询的前端操作符。

例如,您可以将中间语言查询表示为具有三个字段的记录:一个用于SQL查询的SELECT部分,一个用于FROM部分,一个用于WHERE。对于其中的每一个,您分别将标量SQL表达式的抽象表示(用于SELECT,但也用于WHERE)、简单和复杂的关系引用(用于FROM的表名/视图名、内部联接、左外联接等)和复杂布尔谓词表达式(用于WHERE,但也用于标量表达式语言的某些部分)作为值。

完成此操作后,您可以在多个查询对象上实现合并操作,该操作将执行以下操作:

对于结果的SELECT子句,它采用输入SELECT子句的集合联合;

然后,通过编写函数来自己生成它们,并将这些函数的结果提供给查询合并运算符,从而提取在许多查询中重复出现的公共位。

我相信SchemeQL的工作方式非常类似于此。我使用此方法的经验来自于在我的工作中使用受SchemeQL启发的内部语言,但我无法告诉您它们有多相似或不同。我可以告诉你一件事:它真的很管用。

根据定义,关系代数不是一种关系语言吗?换句话说,基于数学关系(来自集合论)而不是数学函数。

这有点像术语混搭。称关系代数为关系语言当然是公平的!但有时当我们说函数式语言时,我们指的是面向数学函数,有时我们指的是非命令式的。RA在第二种意义上是起作用的,但不是第一种意义上的。

";计算可能是由函数";而不是";非命令性的";执行的?例如,您可以将其称为以关系作为数据的一阶函数式语言。

这是一个合理的提议,难道这不意味着C、PASCAL和FORTRAN是函数式语言吗?这似乎不是人们通常所说的意思。

但有时当我们说函数式语言时,我们指的是面向数学函数,有时我们指的是非命令式的。RA在第二种意义上是起作用的,但不是第一种意义上的。

它在第一种意义上也是功能性的。关系运算符是覆盖关系类型的函数。

根据定义,关系代数不是一种关系语言吗?换句话说,基于数学关系(来自集合论)而不是数学函数。

";关系&34;和";函数";是标签,而不是描述。我们称关系代数为关系代数的事实只是一种标签约定。

关系代数实际上是关系类型加上这些类型上的一组高阶函数。关系代数中的每个操作都可以简单地理解为纯函数应用。

难道不是函数关系将项目从Set Domain映射到Set Codomain吗?也就是说,函数_是_集合!

最近,用本地语言而不是中间语言进行关系代数和微积分的实验激增。800磅重的例子是LINQ,但它远远早于Smalltalk的GLORP。艾朗得了健忘症。最近,Ruby也宣布了一个类似的系统:雄心壮志。这些库都避免使用中间语言(让我想起Hibernate的HQL),转而使用本地语言语法。

是的,它真的很管用。我自己的Orms for Python(Geniusql和Dejavu)完全按照您描述的方式使用Python lambdas;甚至还有一个Query对象,它将3个表达式(关系、属性和限制)组合成一个对象。在处理对象集时,这些对象可以直接传递给lambdas;当命中RDBMS后端时,这些相同的lambdas被反编译成等价的SQL。

我的一个有趣的技术说明:每个表达式中的各种关系基于每个lambda的参数顺序对齐,因此限制表达式";lambda x,y:x.Size>;y.Size+10";将x和y映射到属性表达式";lambda a,b:[a.Name,a.Size,b.Size]";中相同的位置参数a和b。

我还将指出CouchDB最近的工作,它更多地落在代数端;在那里,您提供回调来过滤流模型中的对象,根本没有生成SQL。

罗伯特,你把我弄糊涂了。例如LINQ,查询语法/语义类似于SQL,而不是关系代数.。

正确的。其中大多数是关系演算(类似SQL);然而,当编写这样的怪兽时,人们会有一种独特的感觉,尽管API提供了演算,但API背后的实现通常只是从给定的语句中提取表达式,并以(相对固定的)代数方式应用它们。CouchDB将大部分内容公开给开发人员。

我的主要观点很简单,现在有几个工具正在避免引入孤立的中间DSL,而是直接使用本地语言中的表达式的AST或解析树。

我的主要观点很简单,现在有几个工具正在避免引入孤立的中间DSL,而是直接使用本地语言中的表达式的AST或解析树。

在简要地看了几个这样的工具之后,我担心在查询语言中支持的宿主语言部分和不支持的宿主语言部分之间存在边界,并且该边界通常并不明显。您实际上有一个DSL,它是宿主语言的一个子集。

坦率地说,我在Lisp中使用这种中间DSL方法,所以使用宿主语言语法的动机不是很大。中间语言是用s表达式编写的,看起来尽可能像Lisp,但它与宿主语言之间有一个清晰的切入点。

我的主要观点很简单,现在有几个工具正在避免引入孤立的中间DSL,而是直接使用本地语言中的表达式的AST或解析树。

我不太明白,罗伯特。LINQ是DSL吗?不过,我可以看到它被翻译成了C#AST。

我同意这么说,因为它引入了新的关键词和句法结构。但是DSL和API之间的界限非常模糊;我见过的大多数LINQ查询看起来都像C#,带有一些额外的关键字,而不像是一种完全不同的语言。我见过远离宿主语言的配置文件。;)。

其他许多不这样做,通常是因为它们选择用宿主语言实现,因此受到宿主语言的约束。如果您将自己限制为表达式(无语句。

..