标签: functions

优化查询以拆分已知大小的字符串

我有一个带有 . 作为分隔符,它看起来像这样......

abc.efg.hij 
Run Code Online (Sandbox Code Playgroud)

我想要一个将其转换为三列 Col1、Col2 和 Col3 的查询。我想知道最快的方法是什么。到目前为止,由于我有限的数据库经验,我还没有做得很好。我有一个功能:

CREATE FUNCTION [dbo].[split](
   @delimited NVARCHAR(MAX),
   @delimiter NVARCHAR(100)
 ) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
 AS
 BEGIN
   DECLARE @xml XML
   SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'

   INSERT INTO @t(val)
   SELECT  r.value('.','varchar(MAX)') as item
   FROM  @xml.nodes('/t') as records(r)
   RETURN
 END
Run Code Online (Sandbox Code Playgroud)

这就是我现在正在做的事情,但我相信它可以做得更快,我也愿意接受明显更好的功能或用于拆分字符串的开箱即用的想法。我相信我已经运行dbo.split(Name, '.')了三遍并且只能运行一次。

SELECT
      Col1 = (SELECT Val from dbo.split(Name, '.') WHERE Id = '1'),
      Col2 = (SELECT Val from dbo.split(Name, '.')  WHERE Id = '2'),
      Col3 = …
Run Code Online (Sandbox Code Playgroud)

performance sql-server azure-sql-database functions string query-performance

5
推荐指数
2
解决办法
1522
查看次数

Postgresql 9.6 尝试让函数返回字符串而不先将其转换为字符串时出错。

我正在学习 PostgreSQL (9.6) 并且对我收到的错误有点困惑。如果我尝试创建以下函数 II 会收到以下错误。

create or replace FUNCTION HelloWorld ()
RETURNS TABLE(HelloCol text, WorldCol text) AS $$

SELECT 'Hello' , 'World' ;
$$
 LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

错误:

    ERROR:  return type mismatch in function declared to return record
DETAIL:  Final statement returns unknown instead of text at column 1.
CONTEXT:  SQL function "helloworld"
SQL state: 42P13
Run Code Online (Sandbox Code Playgroud)

如果我将文本转换为文本,它可以正常工作。

create or replace FUNCTION HelloWorld ()
RETURNS TABLE(HelloCol text, WorldCol text) AS $$

SELECT cast('Hello' as text) , cast('World' as Text);
$$
 LANGUAGE …
Run Code Online (Sandbox Code Playgroud)

postgresql datatypes functions postgresql-9.6

5
推荐指数
1
解决办法
2180
查看次数

SQL 服务器创建临时函数作为 CTE

我需要创建一个临时函数,用于更大的查询,但我没有对数据库的创建权限(#TEMP 表除外)。

有什么方法可以为此目的使用 CTE 或 #temp 查询。也许我在这里遗漏了一些非常简单的东西。

示例(它可能是什么样子):-

with add1(x) as
  return x+1

select add1(v.Value1), add1(v.Value2)
from Values v
Run Code Online (Sandbox Code Playgroud)

值表

Id Value1 Value2
1  1       4
2  2       5
3  3       6
Run Code Online (Sandbox Code Playgroud)

编辑

根据 Aaron Bertrand 的回答,我设法得到了一些工作。

CREATE TABLE #myTempTable
(
  id int identity(1,1) primary key, 
  amount  int, 
  col1  varchar(10),
  col2 varchar(4)

);
-- quite a few more cols in my actual temp table,  
-- omitted to show the real issue

INSERT #myTempTable(amount,col1, col2) VALUES(10,'a1', 'b1'),(15,'a2','b2');

;WITH processed AS 
( …
Run Code Online (Sandbox Code Playgroud)

sql-server cte functions

5
推荐指数
1
解决办法
2万
查看次数

触发函数更新列

我是 PL/pgSQL 的新手……我使用 Postgres 9.5.0,每次插入新记录时都需要更新一列。该列应从area_pol和 中输入的值中填写area_ofi

我正在尝试创建此功能以适合我的情况:

CREATE OR REPLACE FUNCTION sch_cap.fc_atualiza_dif_area()
  RETURNS trigger AS
$$
BEGIN
    UPDATE
        sch_cap.tbl_cap
    SET
        dif_area = abs(100 - (tbl_cap.area_pol / (tbl_cap.area_ofi * 100)));
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER tg_atualiza_dif_area
  BEFORE INSERT OR UPDATE ON sch_cap.tbl_cap
  FOR EACH ROW EXECUTE PROCEDURE sch_cap.fc_atualiza_dif_area();
Run Code Online (Sandbox Code Playgroud)

但是当我尝试插入记录时,出现以下错误:

错误:超出堆栈深度限制
提示:在确保平台的堆栈深度限制足够后,增加配置参数“max_stack_depth”(当前为 2048kB)。

如何做对?

trigger plpgsql functions postgresql-9.5

5
推荐指数
2
解决办法
1358
查看次数

调用 volatile 函数时,函数可以是不可变的吗?

我有一个函数可以进行一些数学计算。它调用另一个易变的函数。我想知道调用函数是否可以声明为immutableor stable,或者它也必须声明为volatile

postgresql functions

5
推荐指数
1
解决办法
272
查看次数

带有 SELECT 的 SQL 函数与带有 RETURN QUERY SELECT 的 PLPGSQL 函数?

执行 SQL 查询的普通 SQL 函数之间是否有区别:

create function get_sports() returns setof sport as
$body$
    select * from sport;
$body$
language sql stable;
Run Code Online (Sandbox Code Playgroud)

和 PLPGSQL 函数返回相同的 SQL 查询:

create function get_sports() returns setof sport as
$body$
begin
    return query select * from sport;
end
$body$
language plpgsql stable;
Run Code Online (Sandbox Code Playgroud)

关于性能?在什么情况下应该使用哪个版本?

如果我们传递参数,那会改变什么吗?如:

create function get_sports(status int) returns setof sport as
$body$
    select * from sport where status = $1;
$body$
language sql stable;

create function get_sports(status int) returns setof sport as
$body$
begin
    return …
Run Code Online (Sandbox Code Playgroud)

postgresql performance plpgsql functions postgresql-performance

5
推荐指数
1
解决办法
1915
查看次数

PostgreSQL UDF(用户定义函数)开销

免责声明

这项任务可能看起来很深奥,但我还是想创建某种 POC。

目标

我的目标是让 PostgreSQL 数据库(版本 10)向使用它的应用程序公开一个 API。

API 需要采用一组 UDF 的形式:所有函数都属于一个公共方案,这是应用程序唯一可以访问的。桌子和其他东西隐藏在私人计划中。几乎就像,您知道的,面向对象的数据库
这就是我试图让它发挥作用的原因:

  • 它将数据库与应用程序分离,因此您可以重构/优化/非规范化前者,而破坏后者的风险较小。您甚至可以将其维护委托给另一个团队或部门(哦,天哪)
  • API 将服务的要求形式化。数据库当然是一种服务,但称为迁移的传统机制并不能很好地用于弄清楚其中发生了什么。想想多年来收集的成百上千的迁移,其中一些已经损坏,再也不会工作了,并且

好吧,没关系。

问题

因此,当我尝试创建一些非常简单的函数(例如从表中获取所有记录)时,我提到它们总是比它包装的查询慢。虽然这本身是完全可以接受和理解的,但时间差异可能很大。因此,无法接受。

这个例子

我有一张这样的桌子。

CREATE TABLE notifications (
    id SERIAL PRIMARY KEY,
    source_type INTEGER NOT NULL,
    content JSONB,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
)
Run Code Online (Sandbox Code Playgroud)

并且其中有 >120k 条记录。
想象一下,我们想要获得所有这些。
在这里,我们通过一个简单的查询来完成。没有索引,JSONB 数据几乎每条记录 1kb。

EXPLAIN (ANALYZE,VERBOSE,BUFFERS) SELECT * FROM private.notifications;
                                                         QUERY PLAN                                                              
-------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on private.notifications  (cost=0.00..16216.13 rows=120113 width=877) (actual time=0.015..496.473 rows=120113 loops=1)
  Output: id, source_type, content, created
  Buffers: …
Run Code Online (Sandbox Code Playgroud)

postgresql performance plpgsql functions postgresql-performance

5
推荐指数
1
解决办法
940
查看次数

无法针对 EXEC 运行函数

我的 SQL Server 书说你不能在里面运行一个函数EXEC并展示了一个例子:

DECLARE @NumberOfLetters int = 15;
EXEC(‘SELECT LEFT(Name,’ + CAST(@NumberOfLetters AS varchar)
 + ‘) AS ShortName FROM Production.Product’);
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为该CAST()函数需要EXEC在行之前完全解析,因此我们可以将代码修改为:

DECLARE @NumberOfLetters AS int = 15;
DECLARE @str AS varchar(255);
SET @str = ‘SELECT LEFT(Name,’ + CAST(@NumberOfLetters AS varchar) + ‘) AS ShortName FROM Production.Product’;
EXEC(@str);
Run Code Online (Sandbox Code Playgroud)

这次它起作用了,因为如上所述,该CAST()功能需要EXEC在行之前完全解析。

但我还有一个问题,LEFT()函数呢,为什么可以运行EXEC

sql-server syntax functions

5
推荐指数
1
解决办法
282
查看次数

为什么用户定义的标量函数需要模式?

创建用户定义的表函数或用户定义的过程时,可以按命名调用函数或过程。

但是,用户定义的标量函数要求您使用架构调用它:

select dbo.doit(data);
Run Code Online (Sandbox Code Playgroud)

我在其他 DBMS 中没有遇到过这种行为。为什么标量函数是这种情况,而其他函数则不然?

这不仅仅是病态的好奇心,而且我知道问为什么Microsoft 产品是无效的。

如果存在标量函数需要模式而不是其他模式的技术原因,那么值得了解。这不是其他 DBMS 的行为,但可能有技术原因导致这里出现这种情况。

schema sql-server functions

5
推荐指数
1
解决办法
414
查看次数

何时将函数标记为 PARALLEL RESTRICTED 与 PARALLEL SAFE?

Postgres 12 的手册说:

以下操作始终受到并行限制。

  • 扫描公共表表达式 (CTE)。
  • 临时表的扫描。
  • ...

在同一手册页上进一步向下

[...] 同样,PARALLEL RESTRICTED如果函数访问临时表、客户端连接状态、游标、准备好的语句或系统无法跨工作器同步的其他后端本地状态,则必须标记它们。例如,由于最后一个原因setseedrandom受到并行限制。

没有提到 CTE。现在我不确定我是否可以PARALLEL SAFE用于包含 CTE 的函数。对我来说只有PARALLEL RESTRICTED.

上下文:我必须确定现有用户定义函数的最佳标签。该设置是自 Postgres 9.6 以来的新设置,并且可以对性能产生巨大影响,因为涉及PARALLEL SAFE并行工作人员不会执行的功能的操作,PARALLEL RESTRICTED只能由领导者执行。(并PARALLEL USAFE完全禁用并行性。)

在 pgsql-general 上发布了一个相关的问题

postgresql parallelism functions

5
推荐指数
1
解决办法
658
查看次数