SQL用户定义函数介绍
通过<一个data-external-link="true" href="//www.neidfyre.com/blog/author/serge-rielau" aria-label="Serge Rielau">哔叽Rielau一个>而且<一个data-external-link="true" href="//www.neidfyre.com/blog/author/allison-wang" aria-label="Allison Wang">Allison王一个>
2021年10月20日
在bob体育客户端下载平台的博客一个>
2021年10月20日
用户定义函数(UDF)是用户扩展Apache Spark™SQL本机功能的一种方法。自1.3.0以来,Databricks上的SQL已经支持用Scala、Java、Python和R编程语言编写的外部用户定义函数。虽然外部udf非常强大,但也有一些注意事项:
- 安全gydF4y2Ba.用外部语言编写的UDF可能会执行危险甚至恶意代码。这需要严格控制谁可以创建UDF。
- 性能gydF4y2Ba.udf是<一个href="//www.neidfyre.com/glossary/catalyst-optimizer" rel="noopener noreferrer" target="_blank">催化剂优化器一个>.假设Catalyst不知道UDF的内部工作原理,它无法在SQL查询上下文中改进UDF的性能。
- SQL的可用性。gydF4y2Ba对于SQL用户来说,用宿主语言编写udf,然后在Spark中注册它们可能很麻烦。此外,许多用户可能希望对SQL进行一组相当简单的扩展,而开发外部UDF则是多余的。
为了克服上述限制,我们很高兴地介绍一种新的UDF形式:SQL UDF。<一个href="https://docs.www.neidfyre.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-ddl-create-sql-function.html" rel="noopener noreferrer" target="_blank">DBR 9.1 LTS中提供的SQL UDF一个>是完全用SQL的表达能力定义的,而且对SQL编译器完全透明。
使用SQL udf的好处
SQL udf是Databricks上SQL的简单而强大的扩展。作为函数,它们提供了一个抽象层来简化查询构造——使SQL查询更具可读性和模块化。与用非SQL语言编写的udf不同,SQL udf对于SQL用户来说是轻量级的。SQL函数体对于查询优化器是透明的,因此比外部udf性能更好。SQL udf既可以创建为临时函数,也可以创建为永久函数,可以跨多个查询、会话和用户重用,还可以通过访问控制语言(ACL)进行访问控制。在本博客中,我们将通过示例引导您了解SQL udf的一些关键用例。
SQL udf作为常量
让我们从最简单的函数开始:常数。我们都知道我们不应该在代码中使用字面量,因为它会损害可读性,谁知道呢,也许常数并不是恒定的。所以我们只想在一个地方改变它:
创建跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>蓝色()跨度><跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>字符串跨度><跨度>评论跨度><跨风格="color:#183691">“蓝色代码”跨度><跨度>跨度><跨度>语言跨度><跨度>跨度><跨风格="color:#a71d5d">SQL跨度><跨度>跨度><跨度>返回跨度><跨度>跨度><跨风格="color:#183691">0000 ff跨度><跨度>跨度>
如果您熟悉外部udf,您可以看到有一些突出的区别:
- 一个SQL UDF必须定义它的参数列表,即使它是空的。常数不带参数。
- 该函数还声明了它将返回的数据类型。在本例中,它是一个STRING。
- 函数的实现是函数定义的一部分。
- 您指定LANGUAGE SQL来说明它是一个SQL UDF。但实际上,这是不需要的。RETURN子句已经足够暴露了,所以我们决定让它成为可选的。
除了这些差异之外,还有许多与外部UDF相同的东西:
- 你可以替换一个函数。稍后再详细介绍。
- 您可以添加描述函数的注释—如上所示。
- 您甚至可以创建一个只能在当前会话中使用的临时函数。
让我们使用函数:
选择跨度><跨度class="hljs-function" style="color:#458;font-weight:bold">蓝色的跨度><跨度class="hljs-function" style="color:#0086b3">()跨度><跨度>;跨度>0000ff代码>
不出所料,这种方法有效。但是在引擎盖下面发生了什么呢?
解释SELECT blue();跨度>==物理计划==<跨度>*(<跨风格="color:#0086b3">1跨度><跨度>)工程项目[跨度><跨风格="color:#0086b3">0000跨度><跨度>FF<跨风格="color:#a71d5d">作为跨度><跨度>跨度><跨风格="color:#a71d5d">默认的跨度><跨度>.blue ()跨度><跨风格="color:#408080;font-style:italic"># 9)跨度><跨度>跨度><跨度>+ - * (跨度><跨风格="color:#0086b3">1跨度><跨度>扫描OneRowRelation[]跨度>代码>
这太棒了!SQL编译器将函数调用替换为常量本身。
gydF4y2Ba这意味着至少这个SQL UDF的性能成本为零。
现在,让我们来看看另一种常见的用法模式。
SQL UDF封装表达式
假设您不喜欢某些内置函数的命名。也许您正在从另一个产品迁移大量查询,该产品具有不同的函数名和行为。或者,您可能无法忍受在SQL查询中一遍又一遍地复制粘贴一些冗长的表达式。你想要解决这个问题。
使用SQL UDF,我们可以简单地用我们喜欢的名称创建一个新函数:
创建跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>来_hex (x跨度><跨风格="color:#0086b3">INT跨度><跨度>评论跨度><跨风格="color:#183691">“0 - 255之间的任何数字”跨度><跨度>)跨度><跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>字符串跨度><跨度>评论跨度><跨风格="color:#183691">将十进制数转换为十六进制数跨度><跨度>跨度><跨度>包含跨度><跨度>跨度><跨风格="color:#a71d5d">SQL跨度><跨度>跨度><跨风格="color:#a71d5d">确定的跨度><跨度>跨度><跨度>返回跨度><跨度>lpad(十六进制(最小(最大(跨度><跨风格="color:#0086b3">0跨度><跨度>, x),<跨风格="color:#0086b3">255跨度><跨度>)),跨度><跨风格="color:#0086b3">2跨度><跨度>,跨度><跨风格="color:#0086b3">0跨度><跨度>)跨度>代码>
让我们来看看这里使用了哪些新语法:
- 该函数接受一个参数,形参由名称、类型和可选注释定义。
- CONTAINS SQL子句是可选的,但它告诉我们函数不读取或修改表中的任何数据。这是默认设置,所以您通常不会指定它。
- DETERMINISTIC也是可选的,它告诉我们,给定相同的参数,函数总是返回相同的结果集。在这一点上,该子句仅用于文档。但在未来的某个时候,它可能会被用于在某些情况下阻塞非确定性函数。
- 在RETURN子句中,参数是通过名称引用的。在下面的更复杂的场景中,您将看到参数可以通过函数名消除歧义。当然,您可以使用任意复杂的表达式作为函数体。
它不仅有效……
选择跨度><跨度>来_hex (id)跨度><跨风格="color:#a71d5d">从跨度><跨度>跨度><跨风格="color:#a71d5d">范围跨度><跨度>(跨度><跨风格="color:#0086b3">2跨度><跨度>);跨度><跨度>跨度><跨风格="color:#0086b3">00跨度><跨度>跨度><跨度>01跨度><跨度>跨度>
...但效果很好:
解释跨度><跨风格="color:#a71d5d">选择跨度><跨度>来_hex (id)跨度><跨风格="color:#a71d5d">从跨度><跨度>跨度><跨风格="color:#a71d5d">范围跨度><跨度>(跨度><跨风格="color:#0086b3">2跨度><跨度>);跨度><跨度>跨度><跨度 class="hljs-operator">=跨度><跨度class="hljs-operator">=跨度><跨度>物理计划跨度><跨度class="hljs-operator">=跨度><跨度class="hljs-operator">=跨度><跨度>跨度><跨度>*跨度><跨度>(跨度><跨风格="color:#0086b3">1跨度><跨度>)项目[lpad(hex(跨度><跨风格="color:#0086b3">投跨度><跨度>(最小(最大(跨度><跨风格="color:#0086b3">0跨度><跨度>,跨度><跨风格="color:#0086b3">投跨度><跨度>(id #跨度><跨风格="color:#0086b3">0跨度><跨度>跨度><跨风格="color:#a71d5d">作为跨度><跨度>跨度><跨风格="color:#0086b3">int跨度><跨度>)),跨度><跨风格="color:#0086b3">255跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>跨度><跨风格="color:#0086b3">长整型数字跨度><跨度>)),跨度><跨风格="color:#0086b3">2跨度><跨度>,跨度><跨风格="color:#0086b3">0跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>默认的.to_hex (id) #跨度><跨风格="color:#0086b3">1跨度><跨度>]跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>跨度><跨度 class="hljs-operator">*跨度><跨度>(跨度><跨风格="color:#0086b3">1跨度><跨度>)跨度><跨风格="color:#a71d5d">范围跨度><跨度>(跨度><跨风格="color:#0086b3">0跨度><跨度>,跨度><跨风格="color:#0086b3">2跨度><跨度>,一步跨度><跨度class="hljs-operator">=跨度><跨风格="color:#0086b3">1跨度><跨度>,分裂跨度><跨度class="hljs-operator">=跨度><跨风格="color:#0086b3">4跨度><跨度>)跨度>代码>
我们可以看到,物理计划显示了函数lpad,十六进制,最小和最大的直接应用。这与直接调用一系列函数的方法相同。
你也可以用SQL函数组成SQL函数:
创建跨度><跨度class="hljs-function" style="color:#a71d5d">函数跨度><跨度class="hljs-function">rgb_to_hex跨度><跨度class="hljs-function">(跨度><跨度class="hljs-function" style="color:#0086b3">r跨度><跨度class="hljs-function" style="color:#a71d5d">INT跨度><跨度class="hljs-function" style="color:#0086b3">g跨度><跨度class="hljs-function" style="color:#a71d5d">INT跨度><跨度class="hljs-function" style="color:#0086b3">b跨度><跨度class="hljs-function" style="color:#a71d5d">INT跨度><跨度class="hljs-function">)跨度><跨度class="hljs-function">返回跨度><跨度class="hljs-function">字符串跨度><跨度class="hljs-function">评论跨度><跨度class="hljs-function">'跨度><跨度class="hljs-function" style="color:#458;font-weight:bold">转换跨度><跨度class="hljs-function">一个跨度><跨度class="hljs-function">RGB跨度><跨度class="hljs-function">颜色跨度><跨度class="hljs-function">来跨度><跨度class="hljs-function">一个跨度><跨度class="hljs-function">十六进制跨度><跨度class="hljs-function">颜色跨度><跨度class="hljs-function">代码跨度><跨度class="hljs-function">'跨度><跨度class="hljs-function">返回跨度><跨度class="hljs-function">CONCAT跨度><跨度class="hljs-function">(跨度><跨度class="hljs-function" style="color:#0086b3">to_hex (跨度><跨度class="hljs-function" style="color:#0086b3">r跨度><跨度class="hljs-function" style="color:#0086b3">), to_hex (跨度><跨度class="hljs-function" style="color:#0086b3">g跨度><跨度class="hljs-function" style="color:#0086b3">), to_hex (跨度><跨度class="hljs-function" style="color:#0086b3">b跨度><跨度class="hljs-function" style="color:#0086b3">)跨度><跨度class="hljs-function">)跨度><跨度class="hljs-function">选择跨度><跨度class="hljs-function">rgb_to_hex跨度><跨度class="hljs-function">(跨度><跨度class="hljs-function" style="color:#0086b3">0跨度><跨度class="hljs-function" style="color:#0086b3">,跨度><跨度class="hljs-function" style="color:#0086b3">0跨度><跨度class="hljs-function" style="color:#0086b3">,跨度><跨度class="hljs-function" style="color:#0086b3">255跨度><跨度class="hljs-function">)跨度><跨度>;跨度><跨度>跨度><跨风格="color:#0086b3">0000跨度><跨度>FF代码>
从表中读取SQL UDF
SQL UDF的另一个常见用法是对查找进行编码。一个简单的查找方法是将RGB颜色码解码成英文颜色名:
创建跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>from_rgb (rgb字符串跨度><跨度>评论跨度><跨风格="color:#183691">“一个RGB十六进制颜色代码”跨度><跨度>)跨度><跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>字符串跨度><跨度>评论跨度><跨风格="color:#183691">'将RGB颜色代码转换为颜色名称'跨度><跨度>跨度><跨度>返回跨度><跨度>解码(rgb,跨度><跨风格="color:#183691">“就”跨度><跨度>,跨度><跨风格="color:#183691">“红色”跨度><跨度>,跨度><跨度>跨度><跨风格="color:#183691">“FF0080”跨度><跨度>,跨度><跨风格="color:#183691">“玫瑰”跨度><跨度>);跨度><跨度>跨度><跨风格="color:#a71d5d">选择跨度><跨度>from_rgb (跨度><跨风格="color:#183691">“FF0080”跨度><跨度>);跨度>玫瑰代码>
好吧,但是这个世界上的颜色远不止两种。我们希望这个转换是双向的,所以这些应该在查找表中
创建跨度><跨度>跨度><跨风格="color:#a71d5d">表格跨度><跨度>颜色(rgb字符串跨度><跨风格="color:#a71d5d">不跨度><跨度>跨度><跨风格="color:#a71d5d">零跨度><跨度>,名称跨度><跨风格="color:#a71d5d">不跨度><跨度>跨度><跨风格="color:#a71d5d">零跨度><跨度>);跨度><跨度>跨度><跨风格="color:#a71d5d">插入跨度><跨度>跨度><跨风格="color:#a71d5d">成跨度><跨度>颜色跨度><跨风格="color:#a71d5d">值跨度><跨度>跨度><跨度>(跨度><跨风格="color:#183691">“就”跨度><跨度>,跨度><跨风格="color:#183691">“红色”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“FF0080”跨度><跨度>,跨度><跨风格="color:#183691">“玫瑰”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“BFFF00”跨度><跨度>,跨度><跨风格="color:#183691">“石灰”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“7 df9ff”跨度><跨度>,跨度><跨风格="color:#183691">铁蓝色的跨度><跨度>);跨度><跨度>跨度><跨风格="color:#a71d5d">创建跨度><跨度>跨度><跨风格="color:#a71d5d">或跨度><跨度>取代跨度><跨风格="color:#a71d5d">函数跨度><跨度>跨度><跨度>from_rgb(rgb字符串注释跨度><跨风格="color:#183691">“一个RGB十六进制颜色代码”跨度><跨度>)跨度><跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>字符串跨度><跨度>跨度><跨风格="color:#a71d5d">读取跨度><跨度>跨度><跨风格="color:#a71d5d">SQL跨度><跨度>数据跨度><跨风格="color:#a71d5d">SQL跨度><跨度>安全定义者跨度><跨度>评论跨度><跨风格="color:#183691">'将RGB颜色代码转换为颜色名称'跨度><跨度>跨度><跨度>返回跨度><跨度>跨度><跨风格="color:#a71d5d">选择跨度><跨度>跨度><跨风格="color:#a71d5d">第一个跨度><跨度>(名字)跨度><跨风格="color:#a71d5d">从跨度><跨度>颜色跨度><跨风格="color:#a71d5d">在哪里跨度><跨度>rgb<跨度class="hljs-operator">=跨度><跨度>from_rgb.rgb;选择跨度><跨度>from_rgb (rgb)跨度><跨度>跨度><跨风格="color:#a71d5d">从跨度><跨度>跨度><跨风格="color:#a71d5d">值跨度><跨度>(跨度><跨风格="color:#183691">“7 df9ff”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“BFFF00”跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>代码(rgb);跨度>铁蓝色石灰代码>
这里应用了许多新概念:
- 您可以替换一个SQL UDF。为了允许这样做,新函数必须匹配旧函数的签名。函数的签名定义为其参数及其类型的数量。
- 这个函数在表中查找信息,因此您可以选择使用READS SQL DATA记录信息。如果你什么都不声明,SQL编译器将派生正确的值,但你必须不撒谎,并声明CONTAINS SQL。
- SQL SECURITY DEFINER是另一个可选子句,它声明访问颜色表的查询将使用函数所有者的授权。因此,这个功能可以由公众执行,而不影响桌子的安全。
- 就像函数在其所有者的授权下操作一样,它总是在创建时使用当前数据库进行解析。
- ' rgb '是用数字表示的列名。通过限定参数为' from_rgb '。' rgb '说明您指的是参数引用,而不是列。
现在的实际计划是怎样的?很容易看出,使用外部UDF本身执行的查询将导致嵌套循环连接,这是一种消耗宝贵资源的糟糕方式。
解释跨度><跨风格="color:#a71d5d">选择跨度><跨度>from_rgb (rgb)跨度><跨度>跨度><跨风格="color:#a71d5d">从跨度><跨度>跨度><跨风格="color:#a71d5d">值跨度><跨度>(跨度><跨风格="color:#183691">“7 df9ff”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“BFFF00”跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>代码(rgb);跨度><跨度>跨度><跨度 class="hljs-operator">=跨度><跨度class="hljs-operator">=跨度><跨度>物理计划跨度><跨度class="hljs-operator">=跨度><跨度class="hljs-operator">=跨度><跨度>跨度><跨度>AdaptiveSparkPlan isFinalPlan跨度><跨度class="hljs-operator">=跨度><跨风格="color:#954121">假跨度><跨度>跨度><跨度>+跨度><跨度class="hljs-operator">-跨度><跨度>项目(跨度><跨风格="color:#a71d5d">第一个跨度><跨度>(名字)#跨度><跨风格="color:#0086b3">1322268跨度><跨度>跨度><跨风格="color:#a71d5d">作为跨度><跨度>默认的.from_rgb (rgb) #跨度><跨风格="color:#0086b3">1322259跨度><跨度>]跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>BroadcastHashJoin (rgb #跨度><跨风格="color:#0086b3">1322261跨度><跨度>]、[rgb #跨度><跨风格="color:#0086b3">1322266跨度><跨度>, LeftOuter, BuildRight,跨度><跨风格="color:#954121">假跨度><跨度>跨度><跨度>:跨度><跨度class="hljs-operator">-跨度><跨度>LocalTableScan (rgb #跨度><跨风格="color:#0086b3">1322261跨度><跨度>]跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>BroadcastExchange HashedRelationBroadcastMode (ArrayBuffer(输入(跨度><跨风格="color:#0086b3">1跨度><跨度>字符串,跨度><跨风格="color:#954121">假跨度><跨度>]),<跨风格="color:#954121">假跨度><跨度>), [id<跨度class="hljs-operator">=跨度><跨度>#跨度><跨风格="color:#0086b3">1437557跨度><跨度>]跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>SortAggregate(关键跨度><跨度class="hljs-operator">=跨度><跨度>(rgb#<跨风格="color:#0086b3">1322266跨度><跨度>),功能跨度><跨度class="hljs-operator">=跨度><跨度>[finalmerge_first (跨度><跨风格="color:#a71d5d">合并跨度><跨度>跨度><跨风格="color:#a71d5d">第一个跨度><跨度>#跨度><跨风格="color:#0086b3">1322271跨度><跨度>,valueSet #跨度><跨风格="color:#0086b3">1322272跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>跨度><跨风格="color:#a71d5d">第一个跨度><跨度>(名字#跨度><跨风格="color:#0086b3">1322267跨度><跨度>)()#<跨风格="color:#0086b3">1322260跨度><跨度>])跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>排序(rgb #跨度><跨风格="color:#0086b3">1322266跨度><跨度>跨度><跨风格="color:#a71d5d">ASC跨度><跨度>零位跨度><跨风格="color:#a71d5d">第一个跨度><跨度>),<跨风格="color:#954121">假跨度><跨度>,跨度><跨风格="color:#0086b3">0跨度><跨度>跨度><跨度>+跨度><跨度class="hljs-operator">-跨度><跨度>交换hashpartitioning (rgb #跨度><跨风格="color:#0086b3">1322266跨度><跨度>,跨度><跨风格="color:#0086b3">200跨度><跨度>), ENSURE_REQUIREMENTS, [id .跨度><跨度class="hljs-operator">=跨度><跨度>#跨度><跨风格="color:#0086b3">1437553跨度><跨度>]跨度><跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>SortAggregate(关键跨度><跨度class="hljs-operator">=跨度><跨度>(rgb#<跨风格="color:#0086b3">1322266跨度><跨度>),功能跨度><跨度class="hljs-operator">=跨度><跨度>[partial_first(名字#跨度><跨风格="color:#0086b3">1322267跨度><跨度>,跨度><跨风格="color:#954121">假跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>(跨度><跨风格="color:#a71d5d">第一个跨度><跨度>#跨度><跨风格="color:#0086b3">1322271跨度><跨度>,valueSet #跨度><跨风格="color:#0086b3">1322272跨度><跨度>)))<跨度>跨度><跨度 class="hljs-operator">+跨度><跨度class="hljs-operator">-跨度><跨度>排序(rgb #跨度><跨风格="color:#0086b3">1322266跨度><跨度>跨度><跨风格="color:#a71d5d">ASC跨度><跨度>零位跨度><跨风格="color:#a71d5d">第一个跨度><跨度>),<跨风格="color:#954121">假跨度><跨度>,跨度><跨风格="color:#0086b3">0跨度><跨度>跨度><跨度>+跨度><跨度class="hljs-operator">-跨度><跨度>文件可以parquet default.colors[rgb#跨度><跨风格="color:#0086b3">1322266跨度><跨度>、名称#跨度><跨风格="color:#0086b3">1322267跨度><跨度>]跨度>代码>
在本例中,Catalyst选择了广播散列连接而不是嵌套循环连接。它能够这样做是因为它理解SQL UDF的内容。
到目前为止,讨论的所有示例都使用了标量值函数——返回单个值的函数。结果可以是任何类型,甚至是结构、数组和映射的复杂组合。还有另一种类型的UDF需要讨论——表值UDF。
SQL表UDF
想象一下,如果观点有争论!您可以封装复杂的谓词,即使它们依赖于用户提供的值。一个SQL表UDF就是:除了参数以外的任何其他名称的视图。
假设上面的颜色映射不是唯一的。至少,我们可以断言颜色名称在不同的语言中是不同的。
因此,' from_rgb '函数需要修改以返回名称数组或关系。
插入跨度><跨度>跨度><跨风格="color:#a71d5d">成跨度><跨度>颜色跨度><跨风格="color:#a71d5d">值跨度><跨度>(跨度><跨风格="color:#183691">“BFFF00”跨度><跨度>,跨度><跨风格="color:#183691">“citron绿色”跨度><跨度>);跨度>创建跨度><跨度>跨度><跨风格="color:#a71d5d">或跨度><跨度>取代跨度><跨风格="color:#a71d5d">函数跨度><跨度>跨度><跨度>from_rgb(rgb字符串注释跨度><跨风格="color:#183691">“一个RGB十六进制颜色代码”跨度><跨度>)跨度><跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>跨度><跨风格="color:#a71d5d">表格跨度><跨度>(名称字符串注释跨度><跨风格="color:#183691">的颜色名称跨度><跨度>)跨度><跨度>跨度><跨风格="color:#a71d5d">读取跨度><跨度>跨度><跨风格="color:#a71d5d">SQL跨度><跨度>数据跨度><跨风格="color:#a71d5d">SQL跨度><跨度>安全定义者跨度><跨度>评论跨度><跨风格="color:#183691">'将RGB颜色代码转换为颜色名称'跨度><跨度>跨度><跨度>返回跨度><跨度>跨度><跨风格="color:#a71d5d">选择跨度><跨度>的名字跨度><跨风格="color:#a71d5d">从跨度><跨度>颜色跨度><跨风格="color:#a71d5d">在哪里跨度><跨度>rgb<跨度class="hljs-operator">=跨度><跨度>from_rgb.rgb;代码>
如您所见,与标量函数相比,惟一的区别是更复杂的RETURNS子句。与视图不同,SQL udf要求声明返回关系的签名:
- TABLE指定函数返回一个关系。
- TABLE子句必须包含每个返回列的名称和列的数据类型。
- 您可以选择为任何返回列指定注释。
用户定义表函数是DBR的新功能。让我们看看如何调用它们。
选择跨度><跨度>跨度><跨度 class="hljs-operator">*跨度><跨度>跨度><跨风格="color:#a71d5d">从跨度><跨度>from_rgb (跨度><跨风格="color:#183691">“7 df9ff”跨度><跨度>);跨度>铁蓝色代码>
在最简单的形式中,表函数以相同的方式调用,并在引用视图的相同位置调用。唯一的区别是强制大括号,其中包括函数的参数。此函数使用文字参数调用,但参数可以是任何表达式,甚至是标量子查询。
然而,最强大的是在连接中使用SQL表UDF,通常是相关的交叉连接:
选择跨度><跨度>rgb,from_rgb.name跨度><跨度>跨度><跨风格="color:#a71d5d">从跨度><跨度>跨度><跨风格="color:#a71d5d">值跨度><跨度>(跨度><跨风格="color:#183691">“7 df9ff”跨度><跨度>),跨度><跨度>(跨度><跨风格="color:#183691">“BFFF00”跨度><跨度>)跨度><跨风格="color:#a71d5d">作为跨度><跨度>编码(rgb),跨度><跨度>跨度><跨风格="color:#a71d5d">横向跨度><跨度>from_rgb (codes.rgb);跨度><跨度>跨度><跨度 class="hljs-operator"><跨度><跨度>跨风格跨度><跨度class="hljs-operator">=跨度><跨度>“颜色:黑色!重要;”跨度><跨度class="hljs-operator">>跨度><跨风格="color:#0086b3">7跨度><跨度>DF9FF<跨度class="hljs-operator"><跨度><跨度class="hljs-operator">/跨度><跨度>跨度跨度><跨度class="hljs-operator">>跨度><跨度>铁蓝色跨度>BFFF00石灰BFFF00香橼香水代码>
这里的参数指向(关联)FROM子句中前面的(横向)关系。新<一个href="https://docs.www.neidfyre.com/release-notes/runtime/9.0.html" rel="noopener noreferrer" target="_blank">横向关键字一个>允许Catalyst解析这些列。还要注意,可以引用表函数的结果,方法是按照结果签名中定义的列命名,并可选地使用函数名限定列。
政府
当然,现有的GRANT、REVOKE、SHOW、DESCRIBE和DROP语句完全支持SQL udf。
值得详细指出的语句是DESCRIBE。
描述跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>from_rgb;<跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>: default.from_rgb<跨度>类型:跨度><跨风格="color:#a71d5d">表格跨度><跨度>跨度>输入:rgb STRING<跨度>跨度><跨风格="color:#a71d5d">返回跨度><跨度>: name STRING代码>
基本的describe返回你可能期望的东西,但扩展的describe增加了更多的细节:
描述跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>扩展from_rgb;跨度><跨度>跨度><跨风格="color:#a71d5d">函数跨度><跨度>: default.from_rgb<跨度>类型:跨度><跨风格="color:#a71d5d">表格跨度><跨度>跨度><跨度>输入:rgb STRING跨度><跨风格="color:#183691">“一个RGB十六进制颜色代码”跨度><跨度>跨度><跨度>返回跨度><跨度>: name STRING<跨风格="color:#183691">的颜色名称跨度><跨度>跨度><跨度>注释:翻译一个RGB颜色代码跨度><跨风格="color:#a71d5d">成跨度><跨度>颜色名称跨度><跨度>数据访问:跨度><跨风格="color:#a71d5d">读取跨度><跨度>跨度><跨风格="color:#a71d5d">SQL跨度><跨度>数据跨度><跨度>配置:spark.sql.datetime.java8API.enabled跨度><跨度class="hljs-operator">=跨度><跨风格="color:#954121">真正的跨度><跨度>跨度><跨度>spark.sql.hive.version跨度><跨度class="hljs-operator">=跨度><跨风格="color:#0086b3">2.3跨度><跨风格="color:#0086b3">.7跨度><跨度>跨度>老板:serge.rielau<跨度>跨度><跨风格="color:#a71d5d">创建跨度><跨度>跨度><跨风格="color:#0086b3">时间跨度><跨度>:九月三跨度><跨风格="color:#0086b3">08跨度><跨度>跨度><跨风格="color:#0086b3">08跨度><跨度>:跨度><跨风格="color:#0086b3">59跨度><跨度>:跨度><跨风格="color:#0086b3">53跨度><跨度>PDT<跨风格="color:#0086b3">2021跨度><跨度>跨度><跨度>身体:跨度><跨风格="color:#a71d5d">选择跨度><跨度>的名字跨度><跨风格="color:#a71d5d">从跨度><跨度>颜色跨度><跨风格="color:#a71d5d">在哪里跨度><跨度>rgb<跨度class="hljs-operator">=跨度><跨度>from_rgb.rgb代码>
前景
我们所描述的是SQL UDF的初始功能。我们正在考虑的未来扩展包括支持:
- 这样您就可以在数据库中创建一个函数库,并从另一个数据库中订阅它们,就像在您的文件系统中那样。
- udf的重载。
- 具有参数默认值的udf。
SQL udf在SQL可用性方面向前迈进了一大步,可以以许多不同的方式使用,如本文所述。我们鼓励您想出更有创意的方法来利用SQL udf<一个href="//www.neidfyre.com/product/databricks-sql" rel="noopener noreferrer" target="_blank">砖的SQL一个>或使用<一个href="//www.neidfyre.com/product/photon" rel="noopener noreferrer" target="_blank">光子一个>适用于数据工程工作。试<一个href="//www.neidfyre.com/wp-content/uploads/notebooks/sql-user-defined-functions.html" rel="noopener noreferrer" target="_blank">笔记本电脑在这里一个>看看<一个href="https://docs.www.neidfyre.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-ddl-create-sql-function.html" rel="noopener noreferrer" target="_blank">文档一个>获取更多信息。