我有一个带有 . 作为分隔符,它看起来像这样......
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
我正在学习 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) 我需要创建一个临时函数,用于更大的查询,但我没有对数据库的创建权限(#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) 我是 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)。
如何做对?
我有一个函数可以进行一些数学计算。它调用另一个易变的函数。我想知道调用函数是否可以声明为immutableor stable,或者它也必须声明为volatile。
执行 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
这项任务可能看起来很深奥,但我还是想创建某种 POC。
我的目标是让 PostgreSQL 数据库(版本 10)向使用它的应用程序公开一个 API。
API 需要采用一组 UDF 的形式:所有函数都属于一个公共方案,这是应用程序唯一可以访问的。桌子和其他东西隐藏在私人计划中。几乎就像,您知道的,面向对象的数据库。
这就是我试图让它发挥作用的原因:
好吧,没关系。
因此,当我尝试创建一些非常简单的函数(例如从表中获取所有记录)时,我提到它们总是比它包装的查询慢。虽然这本身是完全可以接受和理解的,但时间差异可能很大。因此,无法接受。
我有一张这样的桌子。
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
我的 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?
创建用户定义的表函数或用户定义的过程时,可以按命名调用函数或过程。
但是,用户定义的标量函数要求您使用架构调用它:
select dbo.doit(data);
Run Code Online (Sandbox Code Playgroud)
我在其他 DBMS 中没有遇到过这种行为。为什么标量函数是这种情况,而其他函数则不然?
这不仅仅是病态的好奇心,而且我知道问为什么Microsoft 产品是无效的。
如果存在标量函数需要模式而不是其他模式的技术原因,那么值得了解。这不是其他 DBMS 的行为,但可能有技术原因导致这里出现这种情况。
以下操作始终受到并行限制。
- 扫描公共表表达式 (CTE)。
- 临时表的扫描。
- ...
[...] 同样,
PARALLEL RESTRICTED如果函数访问临时表、客户端连接状态、游标、准备好的语句或系统无法跨工作器同步的其他后端本地状态,则必须标记它们。例如,由于最后一个原因setseed而random受到并行限制。
没有提到 CTE。现在我不确定我是否可以PARALLEL SAFE用于包含 CTE 的函数。对我来说只有PARALLEL RESTRICTED.
上下文:我必须确定现有用户定义函数的最佳标签。该设置是自 Postgres 9.6 以来的新设置,并且可以对性能产生巨大影响,因为涉及PARALLEL SAFE并行工作人员不会执行的功能的操作,PARALLEL RESTRICTED只能由领导者执行。(并PARALLEL USAFE完全禁用并行性。)
我在 pgsql-general 上发布了一个相关的问题。
functions ×10
postgresql ×5
sql-server ×4
performance ×3
plpgsql ×3
cte ×1
datatypes ×1
parallelism ×1
schema ×1
string ×1
syntax ×1
trigger ×1